github.com/raychaser/docker@v1.5.0/engine/http.go (about)

     1  package engine
     2  
     3  import (
     4  	"net/http"
     5  	"path"
     6  )
     7  
     8  // ServeHTTP executes a job as specified by the http request `r`, and sends the
     9  // result as an http response.
    10  // This method allows an Engine instance to be passed as a standard http.Handler interface.
    11  //
    12  // Note that the protocol used in this method is a convenience wrapper and is not the canonical
    13  // implementation of remote job execution. This is because HTTP/1 does not handle stream multiplexing,
    14  // and so cannot differentiate stdout from stderr. Additionally, headers cannot be added to a response
    15  // once data has been written to the body, which makes it inconvenient to return metadata such
    16  // as the exit status.
    17  //
    18  func (eng *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    19  	var (
    20  		jobName         = path.Base(r.URL.Path)
    21  		jobArgs, exists = r.URL.Query()["a"]
    22  	)
    23  	if !exists {
    24  		jobArgs = []string{}
    25  	}
    26  	w.Header().Set("Job-Name", jobName)
    27  	for _, arg := range jobArgs {
    28  		w.Header().Add("Job-Args", arg)
    29  	}
    30  	job := eng.Job(jobName, jobArgs...)
    31  	job.Stdout.Add(w)
    32  	job.Stderr.Add(w)
    33  	// FIXME: distinguish job status from engine error in Run()
    34  	// The former should be passed as a special header, the former
    35  	// should cause a 500 status
    36  	w.WriteHeader(http.StatusOK)
    37  	// The exit status cannot be sent reliably with HTTP1, because headers
    38  	// can only be sent before the body.
    39  	// (we could possibly use http footers via chunked encoding, but I couldn't find
    40  	// how to use them in net/http)
    41  	job.Run()
    42  }