Example #1
0
// SortURLParams return url with sorted get parameters
func SortURLParams(u *url.URL) string {
	query := u.Query()

	if len(query) == 0 {
		return u.RequestURI()
	}

	result := u.Path + "?"

	var sortedQuery []string

	for qp := range query {
		sortedQuery = append(sortedQuery, qp)
	}

	sort.Strings(sortedQuery)

	for _, qp := range sortedQuery {
		value := strings.Join(query[qp], "")

		if value == "" {
			result += qp + "&"
		} else {
			result += qp + "=" + value + "&"
		}
	}

	result = result[0 : len(result)-1]

	if u.Fragment != "" {
		result += "#" + u.Fragment
	}

	return result
}
Example #2
0
File: main.go Project: valyala/ybc
func writeRequests(conn net.Conn, ch <-chan int, requestsChan chan<- int, testUri *url.URL) {
	var requestsWritten int
	w := bufio.NewWriter(conn)
	requestUri := testUri.RequestURI()
	delimiter := "?"
	if strings.Contains(requestUri, "?") {
		delimiter = "&"
	}
	for _ = range ch {
		requestStr := []byte(fmt.Sprintf("GET %s%s%d HTTP/1.1\r\nHost: %s\r\nUser-Agent: go-cdn-booster-bench\r\n\r\n",
			requestUri, delimiter, rand.Intn(*filesCount), testUri.Host))
		if _, err := w.Write(requestStr); err != nil {
			log.Fatalf("Error=[%s] when writing HTTP request [%d] to connection\n", err, requestsWritten)
		}
		requestsWritten += 1
		select {
		case requestsChan <- requestsWritten:
		default:
			if err := w.Flush(); err != nil {
				log.Fatalf("Error when flushing requests' buffer: [%s]\n", err)
			}
			requestsChan <- requestsWritten
		}
		if requestsWritten == *requestsPerConnectionCount {
			break
		}
	}
	if err := w.Flush(); err != nil {
		log.Fatalf("Error when flushing requests' buffer: [%s]\n", err)
	}
}
Example #3
0
// sendUnix sends a request or response via a Unix socket.
func sendUnix(addr *url.URL, payload interface{}) error {
	conn, err := net.Dial("unix", addr.RequestURI())
	if err != nil {
		log.WithFields(log.Fields{
			"error":   err,
			"addr":    addr,
			"payload": payload,
		}).Error("failed to connect to unix socket")
		return err
	}
	defer logx.LogReturnedErr(conn.Close,
		log.Fields{"addr": addr},
		"failed to close unix connection",
	)

	if err := SendConnData(conn, payload); err != nil {
		return err
	}

	resp := &Response{}
	if err := UnmarshalConnData(conn, resp); err != nil {
		return err
	}

	return resp.Error
}
Example #4
0
File: debug.go Project: simonz05/cw
func debugUrl(u *url.URL) {
	logger.Println("Host:", u.Host)
	logger.Println("Path:", u.Path)
	logger.Println("Request URI:", u.RequestURI())
	logger.Println("Scheme:", u.Scheme)
	logger.Println("Query:", u.RawQuery)
	logger.Println("Fragment:", u.Fragment)
	logger.Println("IsAbs:", u.IsAbs())
}
Example #5
0
func parse(s string, base url.URL) (ln []string, as []string) {
	z := html.NewTokenizer(strings.NewReader(s))
	lnm := make(map[string]struct{})
	asm := make(map[string]struct{})

	// anonymous func used to get attribute values
	attr := func(a string) string {
		var av string
		for {
			if k, v, ha := z.TagAttr(); string(k) == a {
				av = string(v)
				break
			} else if ha == false {
				break
			}
		}
		return av
	}

	// convert map to slice
	slc := func(m map[string]struct{}) []string {
		var v []string

		for k := range m {
			v = append(v, k)
		}
		sort.Strings(v)
		return v
	}

	for {
		tt := z.Next()
		switch tt {
		case html.ErrorToken:
			return slc(lnm), slc(asm)
		case html.StartTagToken, html.EndTagToken:
			if tn, ha := z.TagName(); ha {
				tg := string(tn)
				if av := attr(attrs[tg]); av != "" {
					switch tg {
					case atag:
						if url, err := base.Parse(av); err == nil {
							if url.Host == base.Host && url.RequestURI() != base.RequestURI() {
								lnm[url.RequestURI()] = struct{}{}
							}
						}
					case stag, itag, ltag:
						asm[av] = struct{}{}
					}
				}
			}
		}
	}
}
Example #6
0
// NewClientCodec returns a new rpc.ClientCodec using Yar-RPC on conn.
func NewClientHtppCodec(conn io.ReadWriteCloser, u *url.URL, packagerName string) rpc.ClientCodec {
	packer, _ := getPackager(packagerName)
	return &clientHttpCodec{
		r:       bufio.NewReader(conn),
		w:       conn,
		c:       conn,
		host:    u.Host,
		path:    u.RequestURI(),
		pending: make(map[uint64]string),
		packer:  packer,
	}
}
Example #7
0
func (s *V4Signer) canonicalURI(u *url.URL) string {
	canonicalPath := u.RequestURI()
	if u.RawQuery != "" {
		canonicalPath = canonicalPath[:len(canonicalPath)-len(u.RawQuery)-1]
	}
	slash := strings.HasSuffix(canonicalPath, "/")
	canonicalPath = path.Clean(canonicalPath)
	if canonicalPath != "/" && slash {
		canonicalPath += "/"
	}
	return canonicalPath
}
Example #8
0
File: request.go Project: erkl/heat
// NewRequest constructs a minimal Request instance given a method and
// a target URL.
func NewRequest(method string, u *url.URL) *Request {
	return &Request{
		Method: method,
		URI:    u.RequestURI(),
		Major:  1,
		Minor:  1,
		Fields: Fields{
			{"Host", u.Host},
		},
		Scheme: u.Scheme,
		Remote: u.Host,
	}
}
Example #9
0
func normalizePath(p string) string {
	if strings.Contains(p, "./") || strings.Contains(p, "..") {
		p, _ = filepath.Abs(p)
	}

	if strings.Contains(p, "//") {
		p = strings.Replace(p, "//", "/", -1)
	}

	u := url.URL{Path: p}

	return u.RequestURI()
}
Example #10
0
func crawl(url url.URL, ch chan<- SiteMap) {
	var sm SiteMap

	// make sure this link hasn't been crawled
	lc.mux.Lock()
	_, ok := lc.links[url.RequestURI()]

	if !ok {
		lc.links[url.RequestURI()] = struct{}{}
		lc.mux.Unlock()
		log.Printf("Crawling URL: %s\n", url.String())

		b, err := fetch(url)
		if err != nil {
			log.Printf("Error fetching page for URL: %s, err: %s\n", url.String(), err)
			ch <- SiteMap{}
		}

		ln, as := parse(b, url)

		// create new sitemap and add indexed page
		sm = SiteMap{URL: url.String()}
		pg := Page{Path: url.Path, Links: ln, Assets: as}
		sm.Pages = append(sm.Pages, pg)

		c := make(chan SiteMap)
		chLnks := 0
		for _, v := range ln {
			chURL, err := url.Parse(v)
			if err != nil {
				log.Printf("Unable parse url for child link %s, error: %s", v, err)
				continue
			}
			go crawl(*chURL, c)
			chLnks++
		}
		// results of child link crawls
		for i := 0; i < chLnks; i++ {
			chsm := <-c
			if len(chsm.Pages) > 0 {
				sm.Pages = append(sm.Pages, chsm.Pages...)
			}
		}
	} else {
		lc.mux.Unlock()
	}
	// send a SiteMap, even if empty
	ch <- sm
}
Example #11
0
// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
// Copied from gorilla/handlers/handlers.go, converted to strings instead of byte[]
func logHTTP(req *http.Request, url url.URL, ts time.Time, status int, size int) {
	host, _, err := net.SplitHostPort(req.RemoteAddr)

	if err != nil {
		host = req.RemoteAddr
	}

	uri := req.RequestURI

	// Requests using the CONNECT method over HTTP/2.0 must use
	// the authority field (aka r.Host) to identify the target.
	// Refer: https://httpwg.github.io/specs/rfc7540.html#CONNECT
	if req.ProtoMajor == 2 && req.Method == "CONNECT" {
		uri = req.Host
	}
	if uri == "" {
		uri = url.RequestURI()
	}

	log.WithFields(log.Fields{
		"host":   host,
		"method": req.Method,
		"uri":    uri,
		"proto":  req.Proto,
		"status": status,
		"size":   size,
	}).Info(status)
}
Example #12
0
// Log entry for req similar to Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status, size are used to provide the response HTTP status and size.
func buildLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
	username := "-"
	if url.User != nil {
		if name := url.User.Username(); name != "" {
			username = name
		}
	}

	host, _, err := net.SplitHostPort(req.RemoteAddr)

	if err != nil {
		host = req.RemoteAddr
	}

	duration := float64(time.Now().Sub(ts)) / float64(time.Second)

	logLine := fmt.Sprintf("%s - %s [%s] %s %q %s %d %d %q %0.3f\n",
		host,
		username,
		ts.Format("02/Jan/2006:15:04:05 -0700"),
		req.Method,
		url.RequestURI(),
		req.Proto,
		status,
		size,
		req.UserAgent(),
		duration,
	)
	return []byte(logLine)
}
Example #13
0
// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
	username := "-"
	if url.User != nil {
		if name := url.User.Username(); name != "" {
			username = name
		}
	}

	host, _, err := net.SplitHostPort(req.RemoteAddr)

	if err != nil {
		host = req.RemoteAddr
	}

	uri := url.RequestURI()

	buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
	buf = append(buf, host...)
	buf = append(buf, " - "...)
	buf = append(buf, username...)
	buf = append(buf, " ["...)
	buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
	buf = append(buf, `] "`...)
	buf = append(buf, req.Method...)
	buf = append(buf, " "...)
	buf = appendQuoted(buf, uri)
	buf = append(buf, " "...)
	buf = append(buf, req.Proto...)
	buf = append(buf, `" `...)
	buf = append(buf, strconv.Itoa(status)...)
	buf = append(buf, " "...)
	buf = append(buf, strconv.Itoa(size)...)
	return buf
}
Example #14
0
func NewClient(netConn net.Conn, u *url.URL, requestHeader http.Header) (c *Conn, response *http.Response, err error) {
	key, err := calcKey()
	if err != nil {
		return nil, nil, err
	}
	acceptKey := calcAcceptKey(key)

	c = NewConn(netConn, false)

	buf := bytes.NewBufferString("GET ")
	buf.WriteString(u.RequestURI())
	buf.WriteString(" HTTP/1.1\r\nHost: ")
	buf.WriteString(u.Host)
	buf.WriteString("\r\nUpgrade: websocket\r\nConnection: upgrade\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: ")
	buf.WriteString(key)
	buf.WriteString("\r\n")

	for k, vs := range requestHeader {
		for _, v := range vs {
			buf.WriteString(k)
			buf.WriteString(": ")
			buf.WriteString(v)
			buf.WriteString("\r\n")
		}
	}

	buf.WriteString("\r\n")
	p := buf.Bytes()
	if _, err := netConn.Write(p); err != nil {
		return nil, nil, err
	}

	resp, err := http.ReadResponse(c.br, &http.Request{Method: "GET", URL: u})
	if err != nil {
		return nil, nil, err
	}

	if resp.StatusCode != 101 ||
		!strings.EqualFold(resp.Header.Get("Upgrade"), "websocket") ||
		!strings.EqualFold(resp.Header.Get("Connection"), "upgrade") ||
		resp.Header.Get("Sec-Websocket-Accept") != acceptKey {
		return nil, resp, ErrBadHandshake
	}
	return c, resp, nil
}
Example #15
0
// NewClient creates a new client connection using the given net connection.
// The URL u specifies the host and request URI. Use requestHeader to specify
// the origin (Origin), subprotocols (Sec-WebSocket-Protocol) and cookies
// (Cookie). Use the response.Header to get the selected subprotocol
// (Sec-WebSocket-Protocol) and cookies (Set-Cookie).
//
// If the WebSocket handshake fails, ErrBadHandshake is returned along with a
// non-nil *http.Response so that callers can handle redirects, authentication,
// etc.
func NewClient(netConn net.Conn, u *url.URL, requestHeader http.Header, readBufSize, writeBufSize int) (c *Conn, response *http.Response, err error) {
	challengeKey, err := generateChallengeKey()
	if err != nil {
		return nil, nil, err
	}
	acceptKey := computeAcceptKey(challengeKey)

	c = newConn(netConn, false, readBufSize, writeBufSize)
	p := c.writeBuf[:0]
	p = append(p, "GET "...)
	p = append(p, u.RequestURI()...)
	p = append(p, " HTTP/1.1\r\nHost: "...)
	p = append(p, u.Host...)
	// "Upgrade" is capitalized for servers that do not use case insensitive
	// comparisons on header tokens.
	p = append(p, "\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: "...)
	p = append(p, challengeKey...)
	p = append(p, "\r\n"...)
	for k, vs := range requestHeader {
		for _, v := range vs {
			p = append(p, k...)
			p = append(p, ": "...)
			p = append(p, v...)
			p = append(p, "\r\n"...)
		}
	}
	p = append(p, "\r\n"...)

	if _, err := netConn.Write(p); err != nil {
		return nil, nil, err
	}

	resp, err := http.ReadResponse(c.br, &http.Request{Method: "GET", URL: u})
	if err != nil {
		return nil, nil, err
	}
	if resp.StatusCode != 101 ||
		!strings.EqualFold(resp.Header.Get("Upgrade"), "websocket") ||
		!strings.EqualFold(resp.Header.Get("Connection"), "upgrade") ||
		resp.Header.Get("Sec-Websocket-Accept") != acceptKey {
		return nil, resp, ErrBadHandshake
	}
	c.subprotocol = resp.Header.Get("Sec-Websocket-Protocol")
	return c, resp, nil
}
Example #16
0
func TestMakeUserBadHeaderNotBase64Encoded(t *testing.T) {
	re, UserMap := defaultRE(), NewUserMap()
	u := url.URL{Scheme: "http", Host: "localhost:8080", Path: "users"}
	w := httptest.NewRecorder()
	req, _ := http.NewRequest(strings.ToUpper("POST"), u.RequestURI(), nil)
	req.Header.Add("Authorization", "Basic brian:password")
	re.makeUser(UserMap)(w, req)
	code, gotMsg, err := parseResponse(w)
	if err != nil {
		t.Errorf("Problem reading body: %v", err)
	}
	if code != http.StatusBadRequest {
		t.Errorf("unexpected status code: got %v, expected %v", code, http.StatusBadRequest)
	}
	expectedMsg := "You must provide properly-formatted credentials. We could not decode your base64-encoded username/password combination."
	if gotMsg != expectedMsg {
		t.Errorf("unexpected error message: got %v, expected %v", gotMsg, expectedMsg)
	}
}
Example #17
0
//ParseAPIRequestURL takes a net/url URL and returns a models.APIRquest object
func ParseAPIRequestURL(url url.URL) APIRequest {
	r := APIRequest{url, "", ""}
	splited := strings.Split(url.RequestURI(), "/")
	r.Method = splited[2]

	// strip out the beginning of the url and return just the data
	toReplace := fmt.Sprintf("/api/%s/", r.Method)
	r.Query = strings.Replace(url.Path, toReplace, "", 1)
	return r
}
Example #18
0
File: web.go Project: natmeox/mess
func RequireAccount(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		acc := AccountForRequest(w, r)
		if acc == nil {
			v := url.Values{}
			v.Set("next", r.URL.RequestURI())
			signinUrl := url.URL{
				Path:     "/signin",
				RawQuery: v.Encode(),
			}

			http.Redirect(w, r, signinUrl.RequestURI(), http.StatusTemporaryRedirect)
			return
		}

		context.Set(r, ContextKeyAccount, acc)
		h.ServeHTTP(w, r)
	})
}
Example #19
0
// NewClient creates a new client connection using the given net connection.
// The URL u specifies the host and request URI. The header specifies optional
// Origin, Sec-WebSocket-Protocol and Cookie headers.
func NewClient(netConn net.Conn, u *url.URL, header http.Header, readBufSize, writeBufSize int) (c *Conn, subprotocol string, err error) {
	challengeKey, err := generateChallengeKey()
	if err != nil {
		return nil, "", err
	}
	acceptKey := computeAcceptKey(challengeKey)

	c = newConn(netConn, false, readBufSize, writeBufSize)
	p := c.writeBuf[:0]
	p = append(p, "GET "...)
	p = append(p, u.RequestURI()...)
	p = append(p, " HTTP/1.1\r\nHost: "...)
	p = append(p, u.Host...)
	p = append(p, "\r\nUpgrade: websocket\r\nConnection: upgrade\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: "...)
	p = append(p, challengeKey...)
	p = append(p, "\r\n"...)
	for k, vs := range header {
		for _, v := range vs {
			p = append(p, k...)
			p = append(p, ": "...)
			p = append(p, v...)
			p = append(p, "\r\n"...)
		}
	}
	p = append(p, "\r\n"...)

	if _, err := netConn.Write(p); err != nil {
		return nil, "", err
	}

	resp, err := http.ReadResponse(c.br, &http.Request{Method: "GET"})
	if err != nil {
		return nil, "", err
	}
	if resp.StatusCode != 101 ||
		!strings.EqualFold(resp.Header.Get("Upgrade"), "websocket") ||
		!strings.EqualFold(resp.Header.Get("Connection"), "upgrade") ||
		resp.Header.Get("Sec-Websocket-Accept") != acceptKey {
		return nil, "", errors.New("websocket: bad handshake")
	}
	return c, resp.Header.Get("Sec-WebSocket-Protocol"), nil
}
Example #20
0
func (c *appContext) prepareSubmission(s *Submitter) {
	//todo:
	address := url.URL{}
	address.Host = "localhost:3000"
	address.Path = "/unlock/"
	address.Path += s.Id.Hex()
	fmt.Println("URL build result: ",address.RequestURI())
	fmt.Println("Full path: ", address.String()[2:])

	result, err := qrencode.Encode(address.String()[2:], qrencode.ECLevelL)
	if err != nil {
		//handle error
		fmt.Println(err)
		return
	}
	fmt.Println(result.String()
	//todo:

	return
}
Example #21
0
func TestMakeUserBadHeaderTooManyFields(t *testing.T) {
	re, UserMap := defaultRE(), NewUserMap()
	u := url.URL{Scheme: "http", Host: "localhost:8080", Path: "users"}
	w := httptest.NewRecorder()
	req, _ := http.NewRequest(strings.ToUpper("POST"), u.RequestURI(), nil)
	req.Header.Add("foo", "bar")
	req.Header.Add("bar", "foo")
	re.makeUser(UserMap)(w, req)
	code, gotMsg, err := parseResponse(w)
	if err != nil {
		t.Errorf("Problem reading body: %v", err)
	}
	if code != http.StatusBadRequest {
		t.Errorf("unexpected status code: got %v, expected %v", code, http.StatusBadRequest)
	}
	expectedMsg := "You must provide properly-formatted credentials. Expecting HTTP Basic Authentication scheme and base64-encoded username:password pair."
	if gotMsg != expectedMsg {
		t.Errorf("unexpected error message: got %v, expected %v", gotMsg, expectedMsg)
	}
}
Example #22
0
func TestMakeUserBadHeaderNotBasicAuth(t *testing.T) {
	re, UserMap := defaultRE(), NewUserMap()
	u := url.URL{Scheme: "http", Host: "localhost:8080", Path: "users"}
	w := httptest.NewRecorder()
	req, _ := http.NewRequest(strings.ToUpper("POST"), u.RequestURI(), nil)
	var b bytes.Buffer
	enc := base64.NewEncoder(base64.StdEncoding, &b)
	enc.Write([]byte("brian:password"))
	req.Header.Add("Authorization", "NotBasic"+" "+b.String())
	re.makeUser(UserMap)(w, req)
	code, gotMsg, err := parseResponse(w)
	if err != nil {
		t.Errorf("Problem reading body: %v", err)
	}
	if code != http.StatusBadRequest {
		t.Errorf("unexpected status code: got %v, expected %v", code, http.StatusBadRequest)
	}
	expectedMsg := "You must provide properly-formatted credentials. You either did not use the HTTP Basic Authentication scheme or did not provide a username/password field. We have not yet checked whether it is a valid base64 encoding; we have only checked whether the field was present at all."
	if gotMsg != expectedMsg {
		t.Errorf("unexpected error message: got %v, expected %v", gotMsg, expectedMsg)
	}
}
Example #23
0
func (s *Store) RefererId(ref string) (siteId int64, uriId int64, e error) {
	if strings.TrimSpace(ref) == "" {
		return 0, 0, nil
	}
	var u *url.URL
	u, e = url.Parse(ref)
	if e != nil {
		return
	}

	siteId, e = s.SiteId(u.Host)
	if e != nil {
		return
	}

	uriStr := strings.TrimPrefix(u.RequestURI(), "/")
	uriId, e = s.UriId(uriStr)
	if e != nil {
		return
	}
	return
}
Example #24
0
// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
//
// This function was taken from the Gorilla toolkit's handlers.go file.
func buildCommonLogLine(
	req *http.Request,
	url url.URL,
	ts time.Time,
	status int,
	size int) []byte {

	username := "-"
	if url.User != nil {
		if name := url.User.Username(); name != "" {
			username = name
		}
	}

	host, _, err := net.SplitHostPort(req.RemoteAddr)

	if err != nil {
		host = req.RemoteAddr
	}

	uri := req.RequestURI

	// Requests using the CONNECT method over HTTP/2.0 must use
	// the authority field (aka r.Host) to identify the target.
	// Refer: https://httpwg.github.io/specs/rfc7540.html#CONNECT
	if req.ProtoMajor == 2 && req.Method == "CONNECT" {
		uri = req.Host
	}
	if uri == "" {
		uri = url.RequestURI()
	}

	buf := make([]byte, 0, 3*(len(host)+len(username)+
		len(req.Method)+len(uri)+len(req.Proto)+50)/2)
	buf = append(buf, host...)
	buf = append(buf, " - "...)
	buf = append(buf, username...)
	buf = append(buf, " ["...)
	buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
	buf = append(buf, `] "`...)
	buf = append(buf, req.Method...)
	buf = append(buf, " "...)
	buf = appendQuoted(buf, uri)
	buf = append(buf, " "...)
	buf = append(buf, req.Proto...)
	buf = append(buf, `" `...)
	buf = append(buf, strconv.Itoa(status)...)
	buf = append(buf, " "...)
	buf = append(buf, strconv.Itoa(size)...)
	return buf
}
Example #25
0
// streamUnix streams data from a unix socket to a destination writer.
func streamUnix(dest io.Writer, addr *url.URL) error {
	conn, err := net.Dial("unix", addr.RequestURI())
	if err != nil {
		log.WithFields(log.Fields{
			"addr":  addr,
			"error": err,
		}).Error("failed to connect to stream socket")
		return err
	}
	defer logx.LogReturnedErr(conn.Close,
		log.Fields{"addr": addr},
		"failed to close stream connection",
	)

	if _, err := io.Copy(dest, conn); err != nil {
		log.WithFields(log.Fields{
			"addr":  addr,
			"error": err,
		}).Error("failed to stream data")
		return err
	}
	return nil
}
// writeRequestLog writes a log entry to the supplied logrus logger.
// ts is the timestamp with which the entry should be logged.
// trnasactionID is a unique id for this request.
// status and size are used to provide the response HTTP status and size.
func writeRequestLog(logger *log.Logger, req *http.Request, transactionID string, url url.URL, responseTime time.Duration, status, size int) {
	username := "-"
	if url.User != nil {
		if name := url.User.Username(); name != "" {
			username = name
		}
	}

	host, _, err := net.SplitHostPort(req.RemoteAddr)

	if err != nil {
		host = req.RemoteAddr
	}

	uri := req.RequestURI

	// Requests using the CONNECT method over HTTP/2.0 must use
	// the authority field (aka r.Host) to identify the target.
	// Refer: https://httpwg.github.io/specs/rfc7540.html#CONNECT
	if req.ProtoMajor == 2 && req.Method == "CONNECT" {
		uri = req.Host
	}
	if uri == "" {
		uri = url.RequestURI()
	}

	logger.WithFields(log.Fields{
		"responsetime":   int64(responseTime.Seconds() * 1000),
		"host":           host,
		"username":       username,
		"method":         req.Method,
		"transaction_id": transactionID,
		"uri":            uri,
		"protocol":       req.Proto,
		"status":         status,
		"size":           size,
		"referer":        req.Referer(),
		"userAgent":      req.UserAgent(),
	}).Info("")

}
// Log entry for req similar to Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status, size are used to provide the response HTTP status and size.
func buildLogLine(username, upstream string, req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
	if username == "" {
		username = "-"
	}
	if upstream == "" {
		upstream = "-"
	}
	if url.User != nil && username == "-" {
		if name := url.User.Username(); name != "" {
			username = name
		}
	}

	client := req.Header.Get("X-Real-IP")
	if client == "" {
		client = req.RemoteAddr
	}

	if c, _, err := net.SplitHostPort(client); err == nil {
		client = c
	}

	duration := float64(time.Now().Sub(ts)) / float64(time.Second)

	logLine := fmt.Sprintf("%s - %s [%s] %s %s %s %q %s %q %d %d %0.3f\n",
		client,
		username,
		ts.Format("02/Jan/2006:15:04:05 -0700"),
		req.Host,
		req.Method,
		upstream,
		url.RequestURI(),
		req.Proto,
		req.UserAgent(),
		status,
		size,
		duration,
	)
	return []byte(logLine)
}
Example #28
0
// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
// Copied from gorilla/handlers/handlers.go, converted to strings instead of byte[]
func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) string {
	username := "-"
	if url.User != nil {
		if name := url.User.Username(); name != "" {
			username = name
		}
	}

	host, _, err := net.SplitHostPort(req.RemoteAddr)

	if err != nil {
		host = req.RemoteAddr
	}

	uri := req.RequestURI

	// Requests using the CONNECT method over HTTP/2.0 must use
	// the authority field (aka r.Host) to identify the target.
	// Refer: https://httpwg.github.io/specs/rfc7540.html#CONNECT
	if req.ProtoMajor == 2 && req.Method == "CONNECT" {
		uri = req.Host
	}
	if uri == "" {
		uri = url.RequestURI()
	}

	return fmt.Sprintf("%s %s [%s] \"%s %s %s\" %d %d", 
		host, 
		username, 
		ts.Format("02/Jan/2006:15:04:05 -0700"), 
		req.Method, 
		uri, 
		req.Proto, 
		status, 
		size)
}
Example #29
0
func escapedPath(urlObj *url.URL) string {
	// the escape method of url.URL should be public
	// that would avoid this split.
	parts := strings.SplitN(urlObj.RequestURI(), "?", 2)
	return parts[0]
}
Example #30
0
func createRequest(url *url.URL) *http.Request {
	req, _ := http.NewRequest("GET", url.RequestURI(), nil)
	req.Header.Set("User-Agent", "resizr "+Version)
	req.URL = url
	return req
}