Code Monkey home page Code Monkey logo

go.httpgzip's Introduction

go.httpgzip's People

Contributors

arnaud-lb avatar daaku avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

go.httpgzip's Issues

Problem with partial responses (Content-Range)

Go's net/http/fs.go sets the Content-Range header based on offsets in the uncompressed files.

But the Content-Range header applies to entity-body (RFC 2616):

14.16 Content-Range

   The Content-Range entity-header is sent with a partial entity-body to
   specify where in the full entity-body the partial body should be
   applied.

And entity-body is defined as the gzipped stream:

       entity-body := Content-Encoding( Content-Type( data ) )

So I believe that if we try to apply gzip encoding transparently, partial responses will become garbled.

I haven't actually tested whether this is a problem, but since I just spent half an hour investigating the RFC, I figured I'd share this with you.

Question about content type sniffing

What is the purpose of this code in gzipResponseWriter.Write:

if !w.sniffDone {
    if w.Header().Get("Content-Type") == "" {
        w.Header().Set("Content-Type", http.DetectContentType(b))
    }
    w.sniffDone = true
}

When would w.sniffDone ever be true when that first if statement is executed? Wouldn't it be easier to just write w.Header().Set("Content-Type", http.DetectContentType(b))? I may be missing something here, but some clarification would be nice.

Thank you,
cgtdk

Set Vary header?

Should we set Vary: Accept-Encoding, so the response gets cached correctly by any intermediary proxies (CloudFront, etc.)?

I think the Vary may get blown away if a subsequent handler sets a different Vary (e.g. Vary: Cookie), but perhaps it's still worth setting it to cover for most cases.

No response when writing header

When calling w.WriteHeader(http.StatusNotFound) from a handler (for a 404 page in this case) the server gives no response.

This only occurs if the handler is wrapped in a httpgzip.NewHandler

I've made a quick and dirty test case. Save it somewhere and run it using go run main.go and open your browser to http://localhost:9000.

If the call w.WriteHeader(http.StatusNotFound) is removed all four routes work.

package main

import (
    "errors"
    "fmt"
    "net/http"

    "github.com/daaku/go.httpgzip"
)

func show(w http.ResponseWriter, r *http.Request) error {
    fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
    return nil
}

func erroneous(w http.ResponseWriter, r *http.Request) error {
    return errors.New("An error occured")
}

type handler func(resp http.ResponseWriter, req *http.Request) error

func (h handler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
    runHandler(resp, req, h)
}

func runHandler(w http.ResponseWriter, r *http.Request, fn func(http.ResponseWriter, *http.Request) error) {
    err := fn(w, r)
    if err != nil {
        handleError(w, r, http.StatusNotFound, err)
    }
}

func handleError(w http.ResponseWriter, r *http.Request, status int, err error) {
    w.WriteHeader(status) // Comment out this call and everything works
    fmt.Printf("%+v\n", w)
    fmt.Fprintf(w, "Error: %i, %s", status, err)
    fmt.Printf("%+v\n", w)
}

func main() {
    m := http.NewServeMux()
    m.Handle("/", handler(show))
    m.Handle("/gzip", httpgzip.NewHandler(handler(show)))
    m.Handle("/error", handler(erroneous))
    m.Handle("/errorgzip", httpgzip.NewHandler(handler(erroneous)))
    http.ListenAndServe(":9000", m)
}

Do you have any idea on why this happens?

Thank you for your work!

Regards,
Fredrik Wallgren

httpgzip.NewHandler breaks when used with httputil.NewSingleHostReverseProxy

When httputil.NewSingleHostReverseProxy is wrapped with httpgzip.NewHandler, i.e.

http.Handle("/", httpgzip.NewHandler(httputil.NewSingleHostReverseProxy(target)))

the call to w.Writer.Write in gzipResponseWriter.Write returns 0, ErrContentLength ("Conn.Write wrote more than the declared Content-Length"). I believe this is because ReverseProxy.ServeHTTP calls ResponseWriter.WriteHeader which stores the current (pre-gzip) Content-Length value in the response before it writes the body out.

I was able to fix this problem by adding this method to gzipResponseWriter:

func (w *gzipResponseWriter) WriteHeader(code int) {
    w.Header().Del("Content-Length")
    w.ResponseWriter.WriteHeader(code)
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.