// Copyright 2018 Google LLC
//
// 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 proxy

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"strconv"
	"sync"

	"github.com/google/martian"
)

// Replacement for the HAR logging that comes with martian. HAR is not designed for
// replay. In particular, response bodies are interpreted (e.g. decompressed), and we
// just want them to be stored literally. This isn't something we can fix in martian: it
// is required in the HAR spec (http://www.softwareishard.com/blog/har-12-spec/#content).

// LogVersion is the current version of the log format. It can be used to
// support changes to the format over time, so newer code can read older files.
const LogVersion = "0.1"

// A Log is a record of HTTP interactions, suitable for replay. It can be serialized to JSON.
type Log struct {
	Initial []byte // initial data for replay
	Version string // version of this log format
	Entries []*Entry
}

// An Entry  single request-response pair.
type Entry struct {
	ID       string // unique ID
	Request  *Request
	Response *Response
}

// A Request represents an http.Request in the log.
type Request struct {
	Method  string      // http.Request.Method
	URL     string      // http.Request.URL, as a string
	Proto   string      // http.Request.Proto
	Header  http.Header // http.Request.Header
	Body    []byte      // http.Request.Body, read to completion
	Trailer http.Header `json:",omitempty"` // http.Request.Trailer
}

// A Response represents an http.Response in the log.
type Response struct {
	StatusCode int         // http.Response.StatusCode
	Proto      string      // http.Response.Proto
	ProtoMajor int         // http.Response.ProtoMajor
	ProtoMinor int         // http.Response.ProtoMinor
	Header     http.Header // http.Response.Header
	Body       []byte      // http.Response.Body, read to completion
	Trailer    http.Header `json:",omitempty"` // http.Response.Trailer
}

// A Logger maintains a request-response log.
type Logger struct {
	mu      sync.Mutex
	entries map[string]*Entry // from ID
	log     *Log
}

// NewLogger creates a new logger.
func NewLogger() *Logger {
	return &Logger{
		log:     &Log{Version: LogVersion},
		entries: map[string]*Entry{},
	}
}

// ModifyRequest logs requests.
func (l *Logger) ModifyRequest(req *http.Request) error {
	if req.Method == "CONNECT" {
		return nil
	}
	ctx := martian.NewContext(req)
	if ctx.SkippingLogging() {
		return nil
	}
	lreq, err := fromHTTPRequest(req)
	if err != nil {
		return err
	}
	id := ctx.ID()
	entry := &Entry{ID: id, Request: lreq}

	l.mu.Lock()
	defer l.mu.Unlock()

	if _, ok := l.entries[id]; ok {
		panic(fmt.Sprintf("proxy: duplicate request ID: %s", id))
	}
	l.entries[id] = entry
	l.log.Entries = append(l.log.Entries, entry)
	return nil
}

// ModifyResponse logs responses.
func (l *Logger) ModifyResponse(res *http.Response) error {
	ctx := martian.NewContext(res.Request)
	if ctx.SkippingLogging() {
		return nil
	}
	id := ctx.ID()
	lres, err := fromHTTPResponse(res)
	if err != nil {
		return err
	}

	l.mu.Lock()
	defer l.mu.Unlock()

	if e, ok := l.entries[id]; ok {
		e.Response = lres
	}
	// Ignore the response if we haven't seen the request.
	return nil
}

// Extract returns the Log and removes it. The Logger is not usable
// after this call.
func (l *Logger) Extract() *Log {
	l.mu.Lock()
	defer l.mu.Unlock()
	r := l.log
	l.log = nil
	l.entries = nil
	return r
}

func fromHTTPRequest(req *http.Request) (*Request, error) {
	data, err := snapshotBody(&req.Body)
	if err != nil {
		return nil, err
	}
	return &Request{
		Method:  req.Method,
		URL:     req.URL.String(),
		Proto:   req.Proto,
		Header:  redactHeaders(req.Header),
		Body:    data,
		Trailer: req.Trailer,
	}, nil
}

func fromHTTPResponse(res *http.Response) (*Response, error) {
	data, err := snapshotBody(&res.Body)
	if err != nil {
		return nil, err
	}
	return &Response{
		StatusCode: res.StatusCode,
		Proto:      res.Proto,
		ProtoMajor: res.ProtoMajor,
		ProtoMinor: res.ProtoMinor,
		Header:     res.Header,
		Body:       data,
		Trailer:    res.Trailer,
	}, nil
}

func toHTTPResponse(lr *Response, req *http.Request) *http.Response {
	res := &http.Response{
		StatusCode:    lr.StatusCode,
		Proto:         lr.Proto,
		ProtoMajor:    lr.ProtoMajor,
		ProtoMinor:    lr.ProtoMinor,
		Header:        lr.Header,
		Body:          ioutil.NopCloser(bytes.NewReader(lr.Body)),
		ContentLength: int64(len(lr.Body)),
	}
	res.Request = req
	// For HEAD, set ContentLength to the value of the Content-Length header, or -1
	// if there isn't one.
	if req.Method == "HEAD" {
		res.ContentLength = -1
		if c := res.Header["Content-Length"]; len(c) == 1 {
			if c64, err := strconv.ParseInt(c[0], 10, 64); err == nil {
				res.ContentLength = c64
			}
		}
	}
	return res
}

func snapshotBody(body *io.ReadCloser) ([]byte, error) {
	data, err := ioutil.ReadAll(*body)
	if err != nil {
		return nil, err
	}
	(*body).Close()
	*body = ioutil.NopCloser(bytes.NewReader(data))
	return data, nil
}

// Headers that may contain sensitive data (auth tokens, keys).
var sensitiveHeaders = map[string]bool{
	"Authorization":                     true,
	"Proxy-Authorization":               true,
	"X-Goog-Encryption-Key":             true, // used by Cloud Storage for customer-supplied encryption
	"X-Goog-Copy-Source-Encryption-Key": true, // ditto
}

// Copy headers, redacting sensitive ones.
func redactHeaders(hs http.Header) http.Header {
	rh := http.Header{}
	for k, v := range hs {
		if sensitiveHeaders[k] {
			rh.Set(k, "REDACTED")
		} else {
			rh[k] = v
		}
	}
	return rh
}
