hunk.code_window: github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
   github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
  
hunk.labels: keep add
hunk.after_edit: github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
hunk.file_path: go.work.sum
hunk.type: add
file: package docker
  
  import (
  	"errors"
  	"net/http"
  
  	"github.com/portainer/portainer/api/docker"
  	"github.com/portainer/portainer/api/internal/endpointutils"
  
  	"github.com/gorilla/mux"
  	httperror "github.com/portainer/libhttp/error"
  	"github.com/portainer/portainer/api/dataservices"
  	"github.com/portainer/portainer/api/http/handler/docker/containers"
  	"github.com/portainer/portainer/api/http/middlewares"
  	"github.com/portainer/portainer/api/http/security"
  	"github.com/portainer/portainer/api/internal/authorization"
  )
  
  // Handler is the HTTP handler which will natively deal with to external environments(endpoints).
  type Handler struct {
  	*mux.Router
  	requestBouncer       *security.RequestBouncer
  	dataStore            dataservices.DataStore
  	dockerClientFactory  *docker.ClientFactory
  	authorizationService *authorization.Service
  }
  
  // NewHandler creates a handler to process non-proxied requests to docker APIs directly.
  func NewHandler(bouncer *security.RequestBouncer, authorizationService *authorization.Service, dataStore dataservices.DataStore, dockerClientFactory *docker.ClientFactory) *Handler {
  	h := &Handler{
  		Router:               mux.NewRouter(),
  		requestBouncer:       bouncer,
  		authorizationService: authorizationService,
  		dataStore:            dataStore,
  		dockerClientFactory:  dockerClientFactory,
  	}
  
  	// endpoints
  	endpointRouter := h.PathPrefix("/{id}").Subrouter()
  	endpointRouter.Use(middlewares.WithEndpoint(dataStore.Endpoint(), "id"))
  	endpointRouter.Use(dockerOnlyMiddleware)
  
  	containersHandler := containers.NewHandler("/{id}/containers", bouncer, dockerClientFactory)
  	endpointRouter.PathPrefix("/containers").Handler(containersHandler)
  	return h
  }
  
  func dockerOnlyMiddleware(next http.Handler) http.Handler {
  	return http.HandlerFunc(func(rw http.ResponseWriter, request *http.Request) {
  		endpoint, err := middlewares.FetchEndpoint(request)
  		if err != nil {
  			httperror.WriteError(rw, http.StatusInternalServerError, "Unable to find an environment on request context", err)
  			return
  		}
  
  		if !endpointutils.IsDockerEndpoint(endpoint) {
  			errMessage := "environment is not a docker environment"
  			httperror.WriteError(rw, http.StatusBadRequest, errMessage, errors.New(errMessage))
  			return
  		}
  		next.ServeHTTP(rw, request)
  	})
  }
  