handler.go 1.52 KB
Newer Older
1 2 3
package http

import (
4
	"errors"
5 6 7 8 9 10
	"io"
	"net/http"

	cmds "github.com/jbenet/go-ipfs/commands"
)

11
type Handler struct {
12 13
	Ctx  cmds.Context
	Root *cmds.Command
14
}
15

16
var ErrNotFound = errors.New("404 page not found")
17

18 19 20 21 22 23
var mimeTypes = map[string]string{
	cmds.JSON: "application/json",
	cmds.XML:  "application/xml",
	cmds.Text: "text/plain",
}

24
func (i Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
25
	req, err := Parse(r, i.Root)
26
	if err != nil {
27 28 29 30 31 32
		if err == ErrNotFound {
			w.WriteHeader(http.StatusNotFound)
		} else {
			w.WriteHeader(http.StatusBadRequest)
		}
		w.Write([]byte(err.Error()))
33 34
		return
	}
35 36 37
	req.SetContext(i.Ctx)

	// call the command
38
	res := i.Root.Call(req)
39 40

	// set the Content-Type based on res output
41
	if _, ok := res.Output().(io.Reader); ok {
42 43 44 45
		// TODO: set based on actual Content-Type of file
		w.Header().Set("Content-Type", "application/octet-stream")
	} else {
		enc, _ := req.Option(cmds.EncShort)
46 47 48 49 50 51
		encStr, ok := enc.(string)
		if !ok {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		mime := mimeTypes[encStr]
52
		w.Header().Set("Content-Type", mime)
53 54 55 56 57 58 59 60 61 62 63
	}

	// if response contains an error, write an HTTP error status code
	if e := res.Error(); e != nil {
		if e.Code == cmds.ErrClient {
			w.WriteHeader(http.StatusBadRequest)
		} else {
			w.WriteHeader(http.StatusInternalServerError)
		}
	}

64
	out, err := res.Reader()
65 66 67 68
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		w.Header().Set("Content-Type", "text/plain")
		w.Write([]byte(err.Error()))
69
		return
70
	}
71 72

	io.Copy(w, out)
73
}