func TestHTTPDecoder(t *testing.T) { var out []byte if err := codec.NewEncoderBytes(&out, h).Encode(req); err != nil { t.Fatalf("unable to pack test data: %v", err) } r, err := UnpackProxyRequest(out) if err != nil { t.Fatalf("unable to unpack request %v", err) } defer r.Body.Close() if b, _ := ioutil.ReadAll(r.Body); !bytes.Equal(b, body) { t.Fatalf("bad bytes: %s %s", b, body) } if r.Method != method { t.Fatalf("bad method: %s %s", r.Method, method) } if r.Header.Get("X-Cocaine-Service") != "Test" { t.Fatalf("bad header", r.Header.Get("X-Cocaine-Service")) } }
func packRequest(req *http.Request) ([]byte, error) { body, err := ioutil.ReadAll(req.Body) if err != nil { return nil, err } // method uri 1.1 headers body headers := make([][2]string, 0, len(req.Header)) for header, values := range req.Header { for _, val := range values { headers = append(headers, [2]string{header, val}) } } var task []byte codec.NewEncoderBytes(&task, hAsocket).Encode([]interface{}{ req.Method, req.URL.RequestURI(), fmt.Sprintf("%d.%d", req.ProtoMajor, req.ProtoMinor), headers, body, }) return task, nil }
func packMsg(msg messageInterface) rawMessage { var buf []byte err := codec.NewEncoderBytes(&buf, h).Encode([]interface{}{msg.getTypeID(), msg.getSessionID(), msg.getPayload()}) if err != nil { fmt.Println(err) } return buf }
func BenchmarkHTTPDecoder(b *testing.B) { var out []byte codec.NewEncoderBytes(&out, h).Encode(req) for n := 0; n < b.N; n++ { UnpackProxyRequest(out) } }
func convertPayload(in interface{}, out interface{}) error { var buf []byte if err := codec.NewEncoderBytes(&buf, payloadHandler).Encode(in); err != nil { return err } if err := codec.NewDecoderBytes(buf, payloadHandler).Decode(out); err != nil { return err } return nil }
// Sends chunk of data to a client. func (response *Response) Write(data interface{}) { var res []byte codec.NewEncoderBytes(&res, h).Encode(&data) response.from_handler <- packMsg(&chunk{messageInfo{CHUNK, response.session}, res}) }
// WriteHead converts the HTTP status code and the headers to the cocaine format func WriteHead(code int, headers Headers) []byte { var out []byte codec.NewEncoderBytes(&out, h).Encode([]interface{}{code, headers}) return out }
func packTestReq(req []interface{}) []byte { var out []byte codec.NewEncoderBytes(&out, h).Encode(req) return out }
func (o *Overlord) handleHTTPRequest(w http.ResponseWriter, req *http.Request) { defer req.Body.Close() w.Header().Add("X-Powered-By", "Cocaine") body, err := ioutil.ReadAll(req.Body) if err != nil { w.Header().Add("X-Error-Generated-By", "Cocaine") w.WriteHeader(http.StatusBadRequest) fmt.Fprint(w, "unable to read the whole body") return } // method uri 1.1 headers body headers := make([][2]string, 0, len(req.Header)) for header, values := range req.Header { for _, val := range values { headers = append(headers, [2]string{header, val}) } } var task []byte codec.NewEncoderBytes(&task, hAsocket).Encode([]interface{}{ req.Method, req.URL.RequestURI(), fmt.Sprintf("%d.%d", req.ProtoMajor, req.ProtoMinor), headers, body, }) channel := make(chan *cocaine.Message, 5) o.mu.Lock() o.counter++ counter := o.counter o.sessions[o.counter] = channel o.mu.Unlock() defer func() { o.mu.Lock() defer o.mu.Unlock() delete(o.sessions, counter) }() enqueueTask(counter, task, o.conn) var first = true FOR: for msg := range channel { switch msg.MsgType { case chunk: payload, ok := msg.Payload[0].([]byte) if !ok { log.Panicf("invalid response data, must be []byte") continue FOR } if first { first = false var res struct { Code int Headers [][2]string } codec.NewDecoderBytes(payload, hAsocket).Decode(&res) for _, header := range res.Headers { w.Header().Add(header[0], header[1]) } w.WriteHeader(res.Code) continue FOR } w.Write(payload) case _error: log.Println("error message from worker") w.Header().Add("X-Error-Generated-By", "Cocaine") w.WriteHeader(http.StatusInternalServerError) var msgerr struct { CodeInfo [2]int Message string } if err := convertPayload(msg.Payload, &msgerr); err != nil { fmt.Fprintf(w, "unable to decode error reply: %v", err) return } fmt.Fprintf(w, "worker replied with error: [%d] [%d] %s", msgerr.CodeInfo[0], msgerr.CodeInfo[1], msgerr.Message) return case close: // close type return default: // protocol error log.Printf("protocol error: unknown message %v", msg) } } }