conditional

package module
v0.0.0-...-8f5555c Latest Latest
Warning

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

Go to latest
Published: Feb 27, 2020 License: Apache-2.0 Imports: 4 Imported by: 0

README

Conditional

Build Status GoDoc Go Report Card License

Conditional HTTP helpers for Go stdlib's net/http package.

Supported headers:

  • If-Match
  • If-None-Match
  • If-Modified-Since
  • If-Unmodified-Since

Example:

import(
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/bsm/conditional"
)

func main() {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// set ETag and/or Last-Modified headers
		w.Header().Set("ETag", `"strong"`)
		w.Header().Set("Last-Modified", "Fri, 05 Jan 2018 11:25:15 GMT")

		// perform conditional check
		if conditional.Check(w, r) {
			return
		}
		w.WriteHeader(http.StatusNoContent)
	}))
	defer srv.Close()

	client := new(http.Client)

	// make a plain GET request
	req, err := http.NewRequest("GET", srv.URL, nil)
	if err != nil {
		panic(err)
	}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	fmt.Println(res.Status)	// => 204 No Content

	// now, try it with a matchingg "If-Modified-Since"
	req, err = http.NewRequest("GET", srv.URL, nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("If-Modified-Since", "Fri, 05 Jan 2018 11:25:15 GMT")
	res, err = client.Do(req)
	if err != nil {
		panic(err)
	}
	fmt.Println(res.Status)	// => 304 Not Modified

}

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Check

func Check(w http.ResponseWriter, r *http.Request) (done bool)

Check evaluates request preconditions and return true when a precondition resulted in sending http.StatusNotModified or http.StatusPreconditionFailed.

This method relies on ETag and Last-Modified headers being already set on the http.ResponseWriter.

Example (IfMatch)
package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/bsm/conditional"
)

func main() {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// set ETag and/or Last-Modified headers
		w.Header().Set("ETag", `"strong"`)
		w.Header().Set("Last-Modified", "Fri, 05 Jan 2018 11:25:15 GMT")

		// perform conditional check
		if conditional.Check(w, r) {
			return
		}
		w.WriteHeader(http.StatusNoContent)
	}))
	defer srv.Close()

	client := new(http.Client)

	// make a plain GET request
	req, err := http.NewRequest("GET", srv.URL, nil)
	if err != nil {
		panic(err)
	}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	fmt.Println(res.Status) // => 204 No Content

	// now, try it with a matching "If-Match"
	req, err = http.NewRequest("GET", srv.URL, nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("If-Match", `"strong"`)
	res, err = client.Do(req)
	if err != nil {
		panic(err)
	}
	fmt.Println(res.Status) // => 204 No Content

	// finally, try it with a non-matching "If-Match"
	req, err = http.NewRequest("GET", srv.URL, nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("If-Match", `"OTHER-TAG"`)
	res, err = client.Do(req)
	if err != nil {
		panic(err)
	}
	fmt.Println(res.Status) // => 412 Precondition Failed

}
Output:

204 No Content
204 No Content
412 Precondition Failed
Example (IfModifiedSince)
package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/bsm/conditional"
)

func main() {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// set ETag and/or Last-Modified headers
		w.Header().Set("ETag", `"strong"`)
		w.Header().Set("Last-Modified", "Fri, 05 Jan 2018 11:25:15 GMT")

		// perform conditional check
		if conditional.Check(w, r) {
			return
		}
		w.WriteHeader(http.StatusNoContent)
	}))
	defer srv.Close()

	client := new(http.Client)

	// make a plain GET request
	req, err := http.NewRequest("GET", srv.URL, nil)
	if err != nil {
		panic(err)
	}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	fmt.Println(res.Status) // => 204 No Content

	// now, try it with a matchingg "If-Modified-Since"
	req, err = http.NewRequest("GET", srv.URL, nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("If-Modified-Since", "Fri, 05 Jan 2018 11:25:15 GMT")
	res, err = client.Do(req)
	if err != nil {
		panic(err)
	}
	fmt.Println(res.Status) // => 304 Not Modified

}
Output:

204 No Content
304 Not Modified
Example (IfNoneMatch)
package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/bsm/conditional"
)

func main() {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// set ETag and/or Last-Modified headers
		w.Header().Set("ETag", `"strong"`)
		w.Header().Set("Last-Modified", "Fri, 05 Jan 2018 11:25:15 GMT")

		// perform conditional check
		if conditional.Check(w, r) {
			return
		}
		w.WriteHeader(http.StatusNoContent)
	}))
	defer srv.Close()

	client := new(http.Client)

	// make a plain GET request
	req, err := http.NewRequest("GET", srv.URL, nil)
	if err != nil {
		panic(err)
	}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	fmt.Println(res.Status) // => 204 No Content

	// now, try it with a matching "If-None-Match"
	req, err = http.NewRequest("GET", srv.URL, nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("If-None-Match", `"strong"`)
	res, err = client.Do(req)
	if err != nil {
		panic(err)
	}
	fmt.Println(res.Status) // => 304 Not Modified

}
Output:

204 No Content
304 Not Modified

func CheckStatus

func CheckStatus(w http.ResponseWriter, r *http.Request) (code int)

CheckStatus behaves like Check, but returns the http status code that was used for the response instead of a boolean.

http.StatusNotModified
http.StatusPreconditionFailed
0 = response header was not written

func Evaluate

func Evaluate(h http.Header, r *http.Request) int

Evaluate evaluates request preconditions and return the appropriate http status code, which is one of the following:

http.StatusNotModified - content was not modified
http.StatusPreconditionFailed - requested content was modified meanwhile
0 - otherwise.

Unlike Check it does not automatically write a response to the client. Like Check, it relies on ETag and Last-Modified headers being already set.

func NotModified

func NotModified(w http.ResponseWriter)

NotModified writes a http.StatusNotModified response to the user following instructions from RFC 7232 section 4.1:

a sender SHOULD NOT generate representation metadata other than the
above listed fields unless said metadata exists for the purpose of
guiding cache updates (e.g., Last-Modified might be useful if the
response does not have an ETag field).

Types

type ETag

type ETag string

ETag represents an ETag string.

func ScanETag

func ScanETag(s string) (etag ETag, remain string)

ScanETag determines if a syntactically valid ETag is present at s. If so, the ETag and remaining text after consuming ETag is returned. Otherwise, it returns "", "".

Taken from https://golang.org/src/net/http/fs.go. Copyright 2009 The Go Authors. All rights reserved.

func (ETag) IsStrongMatch

func (t ETag) IsStrongMatch(other string) bool

IsStrongMatch returns true if tag matches other strong tag.

func (ETag) IsWeakMatch

func (t ETag) IsWeakMatch(other string) bool

IsWeakMatch returns true if tag matches other tag.

func (ETag) String

func (t ETag) String() string

String returns the ETag as string.

Jump to

Keyboard shortcuts

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