// This downgrades an http.Response object to HTTP 1.0, which is necessary in the case where the // original client request was 1.0. func DowngradeResponse(resp *http.Response, req *http.Request) { resp.Proto = "HTTP/1.0" resp.ProtoMajor = 1 resp.ProtoMinor = 0 if strings.Contains(strings.ToLower(req.Header.Get("Connection")), "keep-alive") { resp.Header.Set("Connection", "keep-alive") resp.Close = false } else { resp.Close = true } }
func (res *HTTPResponseEvent) ToResponse() *http.Response { raw := new(http.Response) raw.Proto = "HTTP" raw.ProtoMajor = 1 raw.ProtoMinor = 1 //raw.Close = true raw.ContentLength = int64(res.Content.Len()) raw.Header = make(http.Header) raw.StatusCode = int(res.Status) res.SetHeader("Content-Length", strconv.Itoa(res.Content.Len())) for i := 0; i < len(res.Headers); i++ { header := res.Headers[i] if strings.EqualFold(header.Name, "Set-Cookie") || strings.EqualFold(header.Name, "Set-Cookie2") { tmp := strings.Split(header.Value, ",") if len(tmp) > 1 { var vlist list.List for _, v := range tmp { if (!strings.Contains(v, "=") || strings.Index(v, "=") > strings.Index(v, ";")) && vlist.Len() > 0 { v = vlist.Back().Value.(string) + "," + v vlist.Remove(vlist.Back()) vlist.PushBack(v) //headerValues.add(headerValues.removeLast() + "," + v); } else { vlist.PushBack(v) } } e := vlist.Front() for { if e == nil { break } raw.Header.Add(header.Name, e.Value.(string)) e = e.Next() } } else { raw.Header.Add(header.Name, header.Value) } } else { raw.Header.Add(header.Name, header.Value) } } if raw.ContentLength > 0 { raw.Body = ioutil.NopCloser(&res.Content) } return raw }
func (t *fakeTransport) RoundTrip(req *http.Request) (*http.Response, error) { body, err := ioutil.ReadAll(req.Body) var in pb.RunQueryRequest var resp http.Response if err = proto.Unmarshal(body, &in); err != nil { // Get back an error resp = http.Response{ StatusCode: http.StatusBadRequest, } } else { // Run our fake query and serialize the response var out pb.RunQueryResponse err := t.Handler(&in, &out) if err != nil { resp = http.Response{ StatusCode: http.StatusBadRequest, } } else { payload, err := proto.Marshal(&out) if err != nil { resp = http.Response{ StatusCode: http.StatusBadRequest, } } else { resp = http.Response{ StatusCode: http.StatusOK, Body: ioutil.NopCloser(bytes.NewBuffer(payload)), } } } } // Set common response fields resp.Proto = "HTTP/1.0" resp.ProtoMajor = 1 resp.ProtoMinor = 1 if resp.Body == nil { resp.Body = ioutil.NopCloser(strings.NewReader("")) } return &resp, nil }
// NewNotification returns a notification response with a specific body content. func NewNotification(body *bytes.Buffer) *http.Response { resp := new(http.Response) resp.Status = "200 OK" resp.StatusCode = http.StatusOK resp.ProtoMajor = 1 resp.ProtoMinor = 0 resp.Body = ioutil.NopCloser(body) resp.ContentLength = int64(body.Len()) resp.Header = map[string][]string{} resp.Header.Set("Content-Type", HTTPContentTypeHAPJson) // Will be ignored unfortunately and won't be fixed https://github.com/golang/go/issues/9304 // Make sure to call FixProtocolSpecifier() instead resp.Proto = "EVENT/1.0" return resp }
func (r *response) Response() *http.Response { if r.Data == nil { r.Data = new(bytes.Buffer) } out := new(http.Response) out.Status = fmt.Sprintf("%d %s", r.StatusCode, http.StatusText(r.StatusCode)) out.StatusCode = r.StatusCode out.Proto = "HTTP/1.1" out.ProtoMajor = 1 out.ProtoMinor = 1 out.Header = r.Header out.Body = &readCloser{r.Data} out.ContentLength = int64(r.Data.Len()) out.TransferEncoding = nil out.Close = true out.Trailer = make(http.Header) out.Request = r.Request return out }
func (p *MockResponseWriter) String() string { resp := new(http.Response) resp.StatusCode = p.StatusCode resp.Proto = "HTTP/1.1" resp.ProtoMajor = 1 resp.ProtoMinor = 1 resp.Header = p.Headers resp.Body = ioutil.NopCloser(bytes.NewBuffer(p.Buffer.Bytes())) resp.ContentLength = int64(p.Buffer.Len()) if p.Headers.Get("Transfer-Encoding") != "" { resp.TransferEncoding = []string{p.Headers.Get("Transfer-Encoding")} } else { resp.TransferEncoding = nil } resp.Close = p.Headers.Get("Connection") == "close" resp.Trailer = make(http.Header) resp.Request = p.Request b, _ := httputil.DumpResponse(resp, true) return string(b) }
func (p proxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { r.Body.Close() conn, _, err := w.(http.Hijacker).Hijack() if err != nil { log.Println("Failed to hijack connection in ProxyConnections.", err) return } defer conn.Close() if _, ok := conn.(*tls.Conn); !ok { log.Println("Recieved a non-TLS connection in ProxyConnections.") return } // Send the connection accepted response. res := new(http.Response) res.Status = "200 Connection Established" res.StatusCode = http.StatusOK res.Proto = "HTTP/1.1" res.ProtoMajor = 1 res.ProtoMinor = 1 if err = res.Write(conn); err != nil { log.Println("Failed to send connection established message in ProxyConnections.", err) return } client, err := NewClientConn(conn, nil, 3, 1) if err != nil { log.Println("Error creating SPDY connection in ProxyConnections.", err) return } go client.Run() // Call user code. p.ProxyConnHandle(client) client.Close() }
// New returns an event response for a characteristic from an accessory. func New(a *accessory.Accessory, c *characteristic.Characteristic) (*http.Response, error) { body, err := Body(a, c) if err != nil { return nil, err } resp := new(http.Response) resp.Status = "200 OK" resp.StatusCode = http.StatusOK resp.ProtoMajor = 1 resp.ProtoMinor = 0 resp.Body = ioutil.NopCloser(body) resp.ContentLength = int64(body.Len()) resp.Header = map[string][]string{} resp.Header.Set("Content-Type", netio.HTTPContentTypeHAPJson) // (brutella) Not sure if Date header must be set // resp.Header.Set("Date", netio.CurrentRFC1123Date()) // Will be ignored unfortunately and won't be fixed https://github.com/golang/go/issues/9304 // Make sure to call FixProtocolSpecifier() instead resp.Proto = "EVENT/1.0" return resp, nil }
func (d *VirtualEndpoint) ServeHTTPForCache(w http.ResponseWriter, r *http.Request) *http.Response { // Check if we are even using this MW var stat RequestStatus var meta interface{} var found bool _, versionPaths, _, _ := d.TykMiddleware.Spec.GetVersionData(r) found, meta = d.TykMiddleware.Spec.CheckSpecMatchesStatus(r.URL.Path, r.Method, versionPaths, VirtualPath) if found { stat = StatusVirtualPath } else { return nil } if stat != StatusVirtualPath { return nil } t1 := time.Now().UnixNano() thisMeta := meta.(*tykcommon.VirtualMeta) // Create the proxy object defer r.Body.Close() originalBody, err := ioutil.ReadAll(r.Body) if err != nil { log.Error("Failed to read request body! ", err) return nil } thisRequestData := RequestObject{ Headers: r.Header, Body: string(originalBody), URL: r.URL.Path, } // We need to copy the body _back_ for the decode r.Body = nopCloser{bytes.NewBuffer(originalBody)} r.ParseForm() thisRequestData.Params = r.Form asJsonRequestObj, encErr := json.Marshal(thisRequestData) if encErr != nil { log.Error("Failed to encode request object for virtual endpoint: ", encErr) return nil } // Encode the configuration data too configData, cErr := d.GetConfig() if cErr != nil { log.Error("Failed to parse configuration data: ", cErr) configData = make(map[string]string) } asJsonConfigData, encErr := json.Marshal(configData) if encErr != nil { log.Error("Failed to encode request object for virtual endpoint: ", encErr) return nil } var thisSessionState = SessionState{} var authHeaderValue = "" // Encode the session object (if not a pre-process) if thisMeta.UseSession { thisSessionState = context.Get(r, SessionData).(SessionState) authHeaderValue = context.Get(r, AuthHeaderValue).(string) } sessionAsJsonObj, sessEncErr := json.Marshal(thisSessionState) if sessEncErr != nil { log.Error("Failed to encode session for VM: ", sessEncErr) return nil } // Run the middleware returnRaw, _ := d.Spec.JSVM.VM.Run(thisMeta.ResponseFunctionName + `(` + string(asJsonRequestObj) + `, ` + string(sessionAsJsonObj) + `, ` + string(asJsonConfigData) + `);`) returnDataStr, _ := returnRaw.ToString() // Decode the return object newResponseData := VMResponseObject{} decErr := json.Unmarshal([]byte(returnDataStr), &newResponseData) if decErr != nil { log.Error("Failed to decode virtual endpoint response data on return from VM: ", decErr) log.Error("--> Returned: ", returnDataStr) return nil } // Save the sesison data (if modified) if thisMeta.UseSession { thisSessionState.MetaData = newResponseData.SessionMeta d.Spec.SessionManager.UpdateSession(authHeaderValue, thisSessionState, 0) } log.Debug("JSVM Virtual Endpoint execution took: (ns) ", time.Now().UnixNano()-t1) responseMessage := []byte(newResponseData.Response.Body) // Create an http.Response object so we can send it tot he cache middleware newResponse := new(http.Response) newResponse.Header = make(map[string][]string) requestTime := time.Now().UTC().Format(http.TimeFormat) for header, value := range newResponseData.Response.Headers { newResponse.Header.Add(header, value) } newResponse.ContentLength = int64(len(responseMessage)) newResponse.Body = ioutil.NopCloser(bytes.NewReader(responseMessage)) newResponse.StatusCode = newResponseData.Response.Code newResponse.Proto = "HTTP/1.0" newResponse.ProtoMajor = 1 newResponse.ProtoMinor = 0 newResponse.Header.Add("Server", "tyk") newResponse.Header.Add("Date", requestTime) // Handle response middleware ResponseHandler := ResponseChain{} chainErr := ResponseHandler.Go(d.TykMiddleware.Spec.ResponseChain, w, newResponse, r, &thisSessionState) if chainErr != nil { log.Error("Response chain failed! ", chainErr) } // Clone the response so we can save it copiedRes := new(http.Response) *copiedRes = *newResponse // includes shallow copies of maps, but okay defer newResponse.Body.Close() // Buffer body data var bodyBuffer bytes.Buffer bodyBuffer2 := new(bytes.Buffer) io.Copy(&bodyBuffer, newResponse.Body) *bodyBuffer2 = bodyBuffer // Create new ReadClosers so we can split output newResponse.Body = ioutil.NopCloser(&bodyBuffer) copiedRes.Body = ioutil.NopCloser(bodyBuffer2) d.HandleResponse(w, newResponse, &thisSessionState) // Record analytics go d.sh.RecordHit(w, r, 0) return copiedRes }
func filterByUrl(w icap.ResponseWriter, req *icap.Request) { h := w.Header() h.Set("ISTag", ISTag) h.Set("Service", "SquidBlocker filter ICAP service") if *debug { fmt.Fprintln(os.Stderr, "Printing the full ICAP request") fmt.Fprintln(os.Stderr, req) fmt.Fprintln(os.Stderr, req.Request) } switch req.Method { case "OPTIONS": h.Set("Methods", "REQMOD, RESPMOD") h.Set("Options-TTL", "1800") h.Set("Allow", "204") h.Set("Preview", "0") h.Set("Transfer-Preview", "*") h.Set("Max-Connections", "4000") h.Set("X-Include", "X-Client-IP, X-Authenticated-Groups, X-Authenticated-User, X-Subscriber-Id") w.WriteHeader(200, nil, false) case "REQMOD": // Check if the method is either OPTIONS\GET\POST\PUT etc // Also to analyse the request stucutre to verify what is the current one used // based on the RFC section at: http://tools.ietf.org/html/rfc7230#section-5.3 // Treat the CONNECT method in a special way due to the fact that it cannot actually be modified. checkhost := "" port := "0" answer := *defaultAnswer var err error if *debug { fmt.Fprintln(os.Stderr, "Default CASE. Request to host: "+req.Request.URL.Host+", Request Method: "+req.Request.Method) fmt.Fprintln(os.Stderr, "The full url from the ICAP client request: "+req.Request.URL.String()) } checkhost, port, err = net.SplitHostPort(req.Request.URL.Host) if err != nil { _ = err checkhost = req.Request.URL.Host } if port != "0" { if *debug { fmt.Fprintln(os.Stderr, "Rquest with port: "+port) } } if req.Request.Method == "CONNECT" && len(checkhost) > 0 && port != "0" { answer = check_tcp(checkhost, port) } else { answer = check(req.Request.URL.String()) } if *debug { fmt.Fprintln(os.Stderr, "ERRlog: reporting answer size => "+strconv.Itoa(len(answer))) fmt.Fprintln(os.Stderr, "ERRlog: reporitng answer => "+answer+", for =>"+req.Request.URL.String()) } // The next part comes to make sure that a DUNO respnse will be handled as the default answer/action if strings.HasPrefix(answer, "DUNO") { answer = *defaultAnswer + " rate=100 default_answer=yes" if *debug { fmt.Fprintln(os.Stderr, "ERRlog: reporting answer startsWith => \"DUNO\", taking default action") if len(*defaultAnswer) > 0 { fmt.Fprintln(os.Stderr, req.Request.URL.String()+" "+*defaultAnswer+" rate=40 default_answer=yes") } else { fmt.Fprintln(os.Stderr, req.Request.URL.String()+" OK state=DUNO") } } } if strings.HasPrefix(answer, "OK") { if *debug { fmt.Fprintln(os.Stderr, "OK response and sending 204 back") } w.WriteHeader(204, nil, false) return } if strings.HasPrefix(answer, "ERR") { if *debug { fmt.Fprintln(os.Stderr, "ERR response and sending 307 redirection back") } resp := new(http.Response) resp.Status = "307 SquidBlocker this url has been filtered!" resp.StatusCode = 307 resp.Proto = "HTTP/1.1" resp.ProtoMajor = 1 resp.ProtoMinor = 1 myMap := make(map[string][]string) //What if it is a connect request myMap["Location"] = append(myMap["Location"], *block_page+"?url="+url.QueryEscape(req.Request.URL.String())) resp.Header = myMap //resp.Body = ioutil.NopCloser(bytes.NewBufferString(body)) //resp.ContentLength = int64(len(body)) resp.Request = req.Request w.WriteHeader(200, resp, true) return } if *debug { fmt.Fprintln(os.Stderr, "Unknown asnwer and scenario, not adapting the request") } w.WriteHeader(204, nil, false) return case "RESPMOD": w.WriteHeader(204, nil, false) default: w.WriteHeader(405, nil, false) if *debug { fmt.Fprintln(os.Stderr, "Invalid request method") } } }
func (rt *RoundTripper) readResponse(c *e3x.Channel) (*http.Response, error) { var ( r = newClientPacketReadCloser(c) resp *http.Response err error ) { // read the header var ( headLenData [2]byte headLen uint16 headerData []byte header map[string]interface{} ) _, err = io.ReadFull(r, headLenData[:]) if err != nil { if err == io.EOF { return nil, io.ErrUnexpectedEOF } return nil, err } headLen = binary.BigEndian.Uint16(headLenData[:]) headerData = make([]byte, headLen) _, err = io.ReadFull(r, headerData) if err != nil { if err == io.EOF { return nil, io.ErrUnexpectedEOF } return nil, err } err = json.Unmarshal(headerData, &header) if err != nil { return nil, err } resp = &http.Response{} if v, p := header[":status"]; p && v != nil { var i int switch w := v.(type) { case int: i = w case int64: i = int(w) case float32: i = int(w) case float64: i = int(w) } if i > 0 { resp.StatusCode = i resp.Status = http.StatusText(i) } delete(header, ":status") } if resp.StatusCode == 0 { return nil, &http.ProtocolError{"missing `status` header"} } resp.Header = make(http.Header, len(header)) resp.Proto = "1.1" resp.ProtoMajor = 1 resp.ProtoMinor = 1 for k, v := range header { if s, ok := v.(string); !ok || s == "" { if k != "status" { resp.Header.Set(http.CanonicalHeaderKey(k), s) } } } } { // set the body resp.Body = r } return resp, nil }
func toShadowD(w icap.ResponseWriter, req *icap.Request) { local_debug := false if strings.Contains(req.URL.RawQuery, "debug=1") { local_debug = true } h := w.Header() h.Set("ISTag", ISTag) h.Set("Service", "Shadower ICAP to WAF Connector") if *debug { fmt.Fprintln(os.Stderr, "Printing the full ICAP request") fmt.Fprintln(os.Stderr, req) fmt.Fprintln(os.Stderr, req.Request) fmt.Fprintln(os.Stderr, req.Response) } switch req.Method { case "OPTIONS": h.Set("Methods", "REQMOD") h.Set("Options-TTL", "1800") h.Set("Allow", "204, 206") h.Set("Preview", "0") h.Set("Transfer-Preview", "*") h.Set("Max-Connections", *maxConnections) h.Set("X-Include", "X-Client-Ip, X-Authenticated-Groups, X-Authenticated-User, X-Subscriber-Id") w.WriteHeader(200, nil, false) case "REQMOD": modified := false nullBody := false allow206 := false allow204 := false xclientip := false if _, allow204Exists := req.Header["Allow"]; allow204Exists { if strings.Contains(req.Header["Allow"][0], "204") { allow204 = true } } if _, allow206Exists := req.Header["Allow"]; allow206Exists { if strings.Contains(req.Header["Allow"][0], "206") { allow206 = true } } if _, xclientipExists := req.Header["X-Client-Ip"]; xclientipExists { if len(req.Header["X-Client-Ip"][0]) > 1 { xclientip = true } } if _, encapsulationExists := req.Header["Encapsulated"]; encapsulationExists { if strings.Contains(req.Header["Encapsulated"][0], "null-body=") { nullBody = true } } if *debug || local_debug { for k, v := range req.Header { fmt.Fprintln(os.Stderr, "The ICAP headers:") fmt.Fprintln(os.Stderr, "key size:", len(req.Header[k])) fmt.Fprintln(os.Stderr, "key:", k, "value:", v) } } _, _, _, _ = nullBody, allow206, modified, allow204 if xclientip { req.Request.RemoteAddr = req.Header["X-Client-Ip"][0] } if wrongMethod(req) { if *debug { fmt.Println("This request has a", req.Request.Method, "method which is not being analyzed") } w.WriteHeader(204, nil, false) return } if *debug || local_debug { for k, v := range req.Request.Header { fmt.Fprintln(os.Stderr, "key:", k, "value:", v) } } // Send the request to ShadowD // If an attack(5,6) was declared then send a custom 500 page // If OK then send a 204 back var resStatus = 1 shodowdres, err := shadowServer.SendToShadowd(req.Request) newmap := make(map[string]interface{}) err = json.Unmarshal([]byte(shodowdres), &newmap) if err != nil { panic(err) } switch int(newmap["status"].(float64)) { case shadowd.STATUS_OK: if *debug || local_debug { fmt.Println("Request reported, OK") } w.WriteHeader(204, nil, false) return case shadowd.STATUS_BAD_REQUEST: resStatus = 400 case shadowd.STATUS_BAD_SIGNATURE: resStatus = 503 case shadowd.STATUS_BAD_JSON: resStatus = 504 case shadowd.STATUS_ATTACK: resStatus = 505 case shadowd.STATUS_CRITICAL_ATTACK: resStatus = 506 default: resStatus = 500 } resp := new(http.Response) resp.Status = "Internal Server Error" resp.StatusCode = resStatus resp.Proto = req.Request.Proto resp.ProtoMajor = req.Request.ProtoMajor resp.ProtoMinor = req.Request.ProtoMinor resp.Request = req.Request myHeaderMap := make(map[string][]string) resp.Header = myHeaderMap resp.Header.Set("X-Ngtech-Proxy", "Shadower") resp.Header.Set("X-Shadower", strconv.Itoa(resStatus)) resp.Header.Set("Content-Type", "text/html") resp.Header.Set("Content-Length", strconv.Itoa(len(internalerrorpage))) w.WriteHeader(200, resp, true) io.WriteString(w, internalerrorpage) return if *debug { fmt.Println("end of the line 204 response!.. Shouldn't happen.") } w.WriteHeader(204, nil, false) return case "RESPMOD": w.WriteHeader(204, nil, false) return default: w.WriteHeader(405, nil, false) if *debug || local_debug { fmt.Fprintln(os.Stderr, "Invalid request method") } } }
// ReadResponse reads an HTTP response. The header is taken from h, // which must include the SPDY-specific fields starting with ':'. // If r is not nil, the body will be read from r. If t is not nil, // the trailer will be taken from t after the body is finished. func ReadResponse(h, t http.Header, r io.Reader, req *http.Request) (*http.Response, error) { for _, s := range badRespHeaderFields { if _, ok := h[s]; ok { return nil, &badStringError{"invalid header field", s} } } var err error resp := new(http.Response) resp.Request = req resp.Close = true resp.Header = make(http.Header) copyHeader(resp.Header, h) f := strings.SplitN(h.Get(":status"), " ", 2) var s string if len(f) > 1 { s = f[1] } resp.Status = f[0] + " " + s resp.StatusCode, err = strconv.Atoi(f[0]) if err != nil { return nil, &badStringError{"malformed HTTP status code", f[0]} } resp.Proto = h.Get(":version") var ok bool resp.ProtoMajor, resp.ProtoMinor, ok = http.ParseHTTPVersion(resp.Proto) if !ok { return nil, &badStringError{"malformed HTTP version", resp.Proto} } realLength, err := fixLength(true, resp.StatusCode, req.Method, resp.Header) if err != nil { return nil, err } if req.Method == "HEAD" { if n, err := parseContentLength(h.Get("Content-Length")); err != nil { return nil, err } else { resp.ContentLength = n } } else { resp.ContentLength = realLength } switch { case realLength == 0: r = eofReader case realLength > 0: if r == nil { // TODO(kr): return error } r = io.LimitReader(r, realLength) } if r == nil { r = eofReader } body := &body{r: r} resp.Body = body if t != nil { body.hdr = resp body.trailer = t } return resp, nil }
func (r *Response) Response() *http.Response { out := new(http.Response) r.headerM.Lock() out.Status = fmt.Sprintf("%d %s", r.StatusCode, http.StatusText(r.StatusCode)) out.StatusCode = r.StatusCode out.Header = r.Header r.headerM.Unlock() out.Proto = "HTTP/1.1" out.ProtoMajor = 1 out.ProtoMinor = 1 r.dataM.Lock() if r.data == nil { out.Body = &ReadCloser{new(bytes.Buffer)} } else if unrequestedGzip(r) { // User-agents MUST support gzip compression. // Regardless of the Accept-Encoding sent by the user-agent, the server may // always send content encoded with gzip or deflate encoding. r.data.Prep() out.Header.Del("Content-Encoding") out.Header.Del("Content-Length") out.ContentLength = -1 out.Body = &gzipReader{body: r.data} } else { r.data.Prep() out.Body = r.data out.ContentLength = r.data.written } r.dataM.Unlock() out.TransferEncoding = nil out.Close = true out.Trailer = make(http.Header) out.Request = r.Request return out }