sheepcounter

package module
v1.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 2, 2022 License: BSD-3-Clause Imports: 5 Imported by: 4

README

SheepCounter GoDoc Report Card

A http.ResponseWriter that can count the bytes written to the client so far.

Why?

If you want to create an access log of how many bytes are sent to which clients, one method would be to write data to a buffer, count the bytes and then send the data to the client. This may be problematic for large files, since it eats up a lot of memory. It is also costly performance wise, since the data would then have to be counted while or after the data is sent to the client.

A better way is to store use the number returned by the Write function directly. This is not straightforward with http.ResponseWriter without wrapping it somehow, which is what this module does. A lightweight struct wraps both a http.ResponseWriter and an uint64, for keeping track of the written bytes.

Examples

Count the bytes sent, per response

package main

import (
        "fmt"
        "github.com/xyproto/sheepcounter"
        "log"
        "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
        sc := sheepcounter.New(w)
        fmt.Fprintf(sc, "Hi %s!", r.URL.Path[1:])
        fmt.Println("COUNTED:", sc.Counter()) // Counts the bytes sent, for this response only
}

func main() {
        http.HandleFunc("/", handler)
        fmt.Println("Serving on port 8080")
        log.Fatal(http.ListenAndServe(":8080", nil))
}

Count the total amount of bytes sent

package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
    "sync/atomic"

    "github.com/xyproto/sheepcounter"
)

const (
    title = "SheepCounter"
    style = `body { margin: 4em; background: wheat; color: black; font-family: terminus, "courier new", courier; font-size: 1.1em; } a:link { color: #403020; } a:visited { color: #403020; } a:hover { color: #605040; } a:active { color: #605040; } #counter { color: red; }`
    page  = "<!doctype html><html><head><style>%s</style><title>%s</title><body>%s</body></html>"
)

var totalBytesWritten uint64

func helloHandler(w http.ResponseWriter, r *http.Request) {
    sc := sheepcounter.New(w)
    body := `<p>Here are the <a href="/counter">counted bytes</a>.</p>`
    fmt.Fprintf(sc, page, style, title, body)
    written, err := sc.UCounter2()
    if err != nil {
        // Log an error and return
        log.Printf("error: %s\n", err)
        return
    }
    atomic.AddUint64(&totalBytesWritten, written)
    log.Printf("counted %d bytes\n", written)
}

func counterHandler(w http.ResponseWriter, r *http.Request) {
    sc := sheepcounter.New(w)
    body := fmt.Sprintf(`<p>Total bytes sent from the server (without counting this response): <span id="counter">%d</span></p><p><a href="/">Back</a></p>`, atomic.LoadUint64(&totalBytesWritten))
    fmt.Fprintf(sc, page, style, title, body)
    written, err := sc.UCounter2()
    if err != nil {
        // Log an error and return
        log.Printf("error: %s\n", err)
        return
    }
    atomic.AddUint64(&totalBytesWritten, written)
    log.Printf("counted %d bytes\n", written)
}

func main() {
    http.HandleFunc("/", helloHandler)
    http.HandleFunc("/counter", counterHandler)

    httpAddr := os.Getenv("HTTP_ADDR")
    if httpAddr == "" {
        httpAddr = ":4000"
    }

    log.Println("Serving on " + httpAddr)
    log.Fatal(http.ListenAndServe(httpAddr, nil))
}

Requirements

  • Go 1.18 or later

General information

Documentation

Overview

Package sheepcounter is a byte counter that wraps a http.ResponseWriter

Index

Constants

This section is empty.

Variables

New is an alias for the NewSheepCounter function

Functions

This section is empty.

Types

type SheepCounter

type SheepCounter struct {
	// contains filtered or unexported fields
}

SheepCounter is a struct that both wraps and implements a http.ResponseWriter

func NewSheepCounter

func NewSheepCounter(w http.ResponseWriter) *SheepCounter

NewSheepCounter creates a struct that wraps an existing http.ResponseWriter

func (*SheepCounter) Counter

func (sc *SheepCounter) Counter() int64

Counter returns the bytes written so far, as an int64. May return a negative number if the counter has overflown math.MaxInt64. Use Counter2() or UCounter2() instead if you wish to catch any overflow that may happen.

func (*SheepCounter) Counter2 added in v1.5.0

func (sc *SheepCounter) Counter2() (int64, error)

Counter2 returns the bytes written so far, as an int64. An error is returned if the counter has overflown.

func (*SheepCounter) Header

func (sc *SheepCounter) Header() http.Header

Header helps fulfill the http.ResponseWriter interface

func (*SheepCounter) Hijack added in v1.2.0

func (sc *SheepCounter) Hijack() (net.Conn, *bufio.ReadWriter, error)

Hijack helps fulfill the http.Hijacker interface

func (*SheepCounter) Reset

func (sc *SheepCounter) Reset()

Reset resets the written bytes counter

func (*SheepCounter) ResponseWriter added in v1.3.0

func (sc *SheepCounter) ResponseWriter() http.ResponseWriter

ReponseWriter returns a pointer to the wrapped http.ResponseWriter

func (*SheepCounter) UCounter added in v1.6.0

func (sc *SheepCounter) UCounter() uint64

UCounter returns the bytes written so far, as an uint64

func (*SheepCounter) UCounter2 added in v1.6.0

func (sc *SheepCounter) UCounter2() (uint64, error)

UCounter2 returns the bytes written so far, as an int64. An error is returned if the counter has overflown.

func (*SheepCounter) Write

func (sc *SheepCounter) Write(data []byte) (int, error)

Write helps fulfill the http.ResponseWriter interface, while also recording the written bytes

func (*SheepCounter) WriteHeader

func (sc *SheepCounter) WriteHeader(statusCode int)

WriteHeader helps fulfill the http.ResponseWriter interface

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL