Skip to content
Snippets Groups Projects
browser.go 1.66 KiB
Newer Older
ale's avatar
ale committed
package reportscollector

import (
	"encoding/json"
ale's avatar
ale committed
	"net"
ale's avatar
ale committed
	"net/http"
ale's avatar
ale committed
	"net/url"
ale's avatar
ale committed
	"time"

	"github.com/jhillyerd/enmime"
ale's avatar
ale committed
)

// Generic browser report as per https://www.w3.org/TR/reporting/.
type report struct {
	Type      string                 `json:"type"`
	Age       int                    `json:"age"`
	URL       string                 `json:"url"`
	UserAgent string                 `json:"user_agent"`
	Body      map[string]interface{} `json:"body"`
}

type ReportHandler struct{}

func (h *ReportHandler) Name() string { return "report-api" }

ale's avatar
ale committed
func (h *ReportHandler) Parse(contentType string, req *http.Request) ([]Event, error) {
	if contentType != "application/reports+json" {
		return nil, ErrNoMatch
	}

	var reports []*report
	if err := json.NewDecoder(req.Body).Decode(&reports); err != nil {
		return nil, err
	}

	var events []Event
	for _, r := range reports {
ale's avatar
ale committed
		events = append(events, h.eventFromReport(req, r))
ale's avatar
ale committed
	}
	return events, nil
}

func (h *ReportHandler) ParseMIME(*enmime.Part) ([]Event, error) {
	return nil, ErrNoMatch
}

ale's avatar
ale committed
func (h *ReportHandler) eventFromReport(req *http.Request, report *report) Event {
ale's avatar
ale committed
	ts := time.Now().Add(time.Duration(-report.Age) * time.Second)

	e := make(Event)
ale's avatar
ale committed
	if asn, ok := lookupASN(getRemoteIP(req)); ok {
		e.Set("asn", asn)
	}
ale's avatar
ale committed
	e.Set("type", report.Type)
	e.Set("event_timestamp", ts)
	e.Set("url", report.URL)
ale's avatar
ale committed
	e.Set("domain", domainFromURL(report.URL))
ale's avatar
ale committed
	e.Set("user_agent", report.UserAgent)
	e.Set("body", report.Body)
	return e
}
ale's avatar
ale committed

func domainFromURL(u string) string {
	if uri, err := url.Parse(u); err == nil {
		if host, _, err := net.SplitHostPort(uri.Host); err == nil {
			return host
		}
		return uri.Host
	}
	return ""
}