Browse code

Engine: convenience http transport for simple remote job execution

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