|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- // Copyright 2015 Google Inc. All rights reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
-
- /*
- Package proxyutil provides functionality for building proxies.
- */
- package proxyutil
-
- import (
- "bytes"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "regexp"
- "strconv"
- "strings"
- "time"
- )
-
- // NewResponse builds new HTTP responses.
- // If body is nil, an empty byte.Buffer will be provided to be consistent with
- // the guarantees provided by http.Transport and http.Client.
- func NewResponse(code int, body io.Reader, req *http.Request) *http.Response {
- if body == nil {
- body = &bytes.Buffer{}
- }
-
- rc, ok := body.(io.ReadCloser)
- if !ok {
- rc = ioutil.NopCloser(body)
- }
-
- res := &http.Response{
- StatusCode: code,
- Status: fmt.Sprintf("%d %s", code, http.StatusText(code)),
- Proto: "HTTP/1.1",
- ProtoMajor: 1,
- ProtoMinor: 1,
- Header: http.Header{},
- Body: rc,
- Request: req,
- }
-
- if req != nil {
- res.Close = req.Close
- res.Proto = req.Proto
- res.ProtoMajor = req.ProtoMajor
- res.ProtoMinor = req.ProtoMinor
- }
-
- return res
- }
-
- // Warning adds an error to the Warning header in the format: 199 "martian"
- // "error message" "date".
- func Warning(header http.Header, err error) {
- date := header.Get("Date")
- if date == "" {
- date = time.Now().Format(http.TimeFormat)
- }
-
- w := fmt.Sprintf(`199 "martian" %q %q`, err.Error(), date)
- header.Add("Warning", w)
- }
-
- // GetRangeStart returns the byte index of the start of the range, if it has one.
- // Returns 0 if the range header is absent, and -1 if the range header is invalid or
- // has multi-part ranges.
- func GetRangeStart(res *http.Response) int64 {
- if res.StatusCode != http.StatusPartialContent {
- return 0
- }
-
- if strings.Contains(res.Header.Get("Content-Type"), "multipart/byteranges") {
- return -1
- }
-
- re := regexp.MustCompile(`bytes (\d+)-\d+/\d+`)
- matchSlice := re.FindStringSubmatch(res.Header.Get("Content-Range"))
-
- if len(matchSlice) < 2 {
- return -1
- }
-
- num, err := strconv.ParseInt(matchSlice[1], 10, 64)
-
- if err != nil {
- return -1
- }
- return num
- }
-
|