2016-08-24 1 views
0

나는 가기가 좋다. 하지만 REST API를 가지고 놀고 있습니다. 난 내가 http 응답 텍스트에 gzip 압축

내가 내 응답 gzip을이 기능을 사용하고자이 두 가지 기능에 json.Encoder로 json.Marshal에서 같은 동작을 얻을 캔트 :

func gzipFast(a *[]byte) []byte { 
    var b bytes.Buffer 
    gz := gzip.NewWriter(&b) 
    defer gz.Close() 
    if _, err := gz.Write(*a); err != nil { 
     panic(err) 
    } 
    return b.Bytes() 
} 

을하지만이 기능이 반환

내가 주석을 해제 할 때

func CompressedGet(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { 

    box := Box{Width: 10, Height: 20, Color: "gree", Open: false} 
    box.ars = make([]int, 100) 
    for i := range box.ars { 
     box.ars[i] = i 
    } 
    //fmt.Println(r.Header.Get("Content-Encoding")) 

    w.Header().Set("Content-Type", "application/json") 
    w.Header().Set("Content-Encoding", "gzip") 
    b, _ := json.Marshal(box) 
    //fmt.Println(len(b)) 
    //fmt.Println(len(gzipFast(&b))) 

    fmt.Fprint(w, gzipFast(&b)) 
    //fmt.Println(len(gzipSlow(b))) 
    //gz := gzip.NewWriter(w) 
    //defer gz.Close() 
    //json.NewEncoder(gz).Encode(box) 
    r.Body.Close() 

} 

:하지만 여기

curl http://localhost:8081/compressedget --compressed --verbose 
* Trying 127.0.0.1... 
* Connected to localhost (127.0.0.1) port 8081 (#0) 
> GET /compressedget HTTP/1.1 
> Host: localhost:8081 
> User-Agent: curl/7.47.0 
> Accept: */* 
> Accept-Encoding: deflate, gzip 
> 
< HTTP/1.1 200 OK 
< Content-Encoding: gzip 
< Content-Type: application/json 
< Date: Wed, 24 Aug 2016 00:59:38 GMT 
< Content-Length: 30 
< 
* Connection #0 to host localhost left intact 

는 이동 기능입니다

//gz := gzip.NewWriter(w) 
//defer gz.Close() 
//json.NewEncoder(gz).Encode(box) 

잘 작동합니다.

+0

3 줄이 필요하지 않을 수 있습니다. gzipFast 함수는 이미 json으로 인코딩 된 상자의 gzipping을 수행하고 있습니다. – Sridhar

답변

1

기본 바이트에 액세스하기 전에 gzip 작성기를 플러시하거나 닫아야합니다. gzip을 작가의 버퍼 있었지만 아직 최종 스트림에 기록이야 그렇지 않으면 무엇을

func gzipFast(a *[]byte) []byte { 
    var b bytes.Buffer 
    gz := gzip.NewWriter(&b) 
    if _, err := gz.Write(*a); err != nil { 
     gz.Close() 
     panic(err) 
    } 
    gz.Close() 
    return b.Bytes() 
} 

는 최대 수집지고 있지 않습니다.

+0

이렇게 수정했습니다. 감사! – stihl

1

문제는 fmt.Fprint(w, gzipFast(&b))의 사용이라고 생각합니다.

gzipFast의 정의를 보면 []byte을 반환합니다. 이 슬라이스를 인쇄 기능에 넣으면 모든 것을 "인쇄 중"w에 저장됩니다. 당신이 io.Writer의 정의를 보면

는 :

type Writer interface { 
     Write(p []byte) (n int, err error) } 

당신은 작가가 입력으로 []byte을 처리 할 수있는 것을 알 수있다.

fmt.Fprint(w, gzipFast(&b)) 대신 w.Write(gzipFast(&b))을 사용해야합니다. 그런 다음 주석을 해제 할 필요가 없습니다 : 코드에서 무슨 일이 일어나고 있는지 보여주는 작은 예를 들어, 같은

//gz := gzip.NewWriter(w) 
//defer gz.Close() 
//json.NewEncoder(gz).Encode(box) 

모든 것 :

https://play.golang.org/p/6rzqLWTGiI

0

나는 피할 것이다 gzip으로 보내고 수동 []byte합니다. 표준 라이브러리의 기존 작성자를 쉽게 사용할 수 있습니다. 또한 compress/flate을 살펴보고 gzip 대신 사용해야한다고 생각합니다.

package main 

import (
    "net/http" 
    "encoding/json" 
    "compress/gzip" 
    "log" 
) 

type Box struct { 
    Width int `json:"width"` 
} 

func writeJsonResponseCompressed(w http.ResponseWriter, r *http.Request) { 

    box := &Box{Width: 10} 

    w.Header().Set("Content-Type", "application/json") 
    w.Header().Set("Content-Encoding", "gzip") 

    body, err := json.Marshal(box) 
    if err != nil { 
     // Your error handling 
     return 
    } 

    writer, err := gzip.NewWriterLevel(w, gzip.BestCompression) 
    if err != nil { 
     // Your error handling 
     return 
    } 

    defer writer.Close() 

    writer.Write(body) 
} 

func main() { 
    http.HandleFunc("/compressedget", writeJsonResponseCompressed) 
    log.Fatal(http.ListenAndServe(":8081", nil)) 
} 
+0

나는 이것이 몇 가지 것을 배우기위한 시험이라는 사실에 동의한다. 이 API가 프로덕션 응용 프로그램이라면 솔루션이 가장 좋습니다. – stihl