Commit 7893f481 authored by Geoff Simmons's avatar Geoff Simmons

Initial commit

parents
*~
# Generated
http-echo
main_version.go
See LICENSE for details.
FROM golang:1.10.5 as builder
RUN /usr/sbin/adduser --system --no-create-home http-echo
RUN go get -d -v github.com/slimhazard/gogitversion && \
cd /go/src/github.com/slimhazard/gogitversion && \
make install
WORKDIR $GOPATH/src/code.uplex.de/uplex-varnish/http-echo
COPY . .
RUN go generate && \
GOOS=linux GOARCH=amd64 go build -tags netgo -ldflags='-w -s' \
-o /go/bin/http-echo
FROM scratch
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /go/bin/http-echo /go/bin/http-echo
USER http-echo
ENTRYPOINT ["/go/bin/http-echo"]
Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
# Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung
# All rights reserved
#
# Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
all: build doc
http-echo: main.go
go fmt
go generate
go build -o http-echo
build: http-echo
README.md: doc.go
godoc -html . | pandoc -f html -t markdown_github > README.md
doc: README.md
check: build
golint
go vet
test: check
clean:
go clean
rm -f main_version.go
rm -f http-echo
install: all
go install
VERSION=`git describe --always 2>/dev/null || echo unknown`
container:
docker build -t http-echo:${VERSION} -f Dockerfile .
http-echo is an HTTP server that echoes all requests in the response.
### SYNOPSIS
.
http-echo [-address host:port] [-log logfile] [-set_prefix prefix]
[-version]
### DESCRIPTON
http-echo is an HTTP server that returns a brief summary of the request as well as the request header and body in the response body. It may also set response headers as specified in request headers that have a special prefix (default 'X-Set-') in the request header name.
For example, if http-echo is listening at its default port 7357 on localhost:
$ curl -d 'foo=bar&baz=quux' http://localhost:7357/foo/bar/baz
Server address: 127.0.0.1:7357
Server name: myhostname
Date: 05/Apr/2019:23:37:11 +0200
URI: /foo/bar/baz
Request ID: 9566c74d10037c4d7bbb0407d1e2c649
POST /foo/bar/baz HTTP/1.1
Host: localhost:7357
User-Agent: curl/7.52.1
Content-Length: 16
Accept: */*
Content-Type: application/x-www-form-urlencoded
foo=bar&baz=quux
http-echo returns status 200 OK for every request that it receives, for any URL and request method.
The response body begins with these five lines, followed by the request header and body:
Server address: <address at which the request was received>
Server name: <hostname on which http-echo is running>
Date: <date/time at which the request was received>
URI: <URL path>
Request ID: <ID generated by http-echo for the request>
Request headers with a special prefix, default 'X-Set-', may be used to set response headers. If the request has such a header, then the part of the header name after the prefix becomes the response header name, and the value of the request header becomes the value of the response header.
There can be multiple headers with the "set" prefix in the request, all of which set a response header. If more than one "set" request header designates response headers with the same name, then multiple response headers with that name are set in the response.
For example:
# Using curl -I to show the response headers:
$ curl -I -H 'X-Set-Foo: bar' -H 'X-Set-Baz: quux' http://localhost:7357/foo/bar/baz
HTTP/1.1 200 OK
Baz: quux
Content-Type: text/plain
Foo: bar
Date: Fri, 05 Apr 2019 22:23:08 GMT
Content-Length: 273
# Set the same response header name more than once:
$ curl -I -H 'X-Set-Foo: bar' -H 'X-Set-Foo: baz' http://localhost:7357/foo/bar/baz
HTTP/1.1 200 OK
Content-Type: text/plain
Foo: bar
Foo: baz
Date: Fri, 05 Apr 2019 22:25:26 GMT
Content-Length: 272
### OPTIONS
http-echo may be used with these command-line flags:
-address host:port
Use 'host:port' as the address at which http-echo listens. The host must be a literal IP address or a host name that can be resolved to IP addresses. If the host is a literal IPv6 address, it must be enclosed in square brackets. If the host is empty or a literal unspecified IP address, as in ":80", "0.0.0.0:80" or "\[::\]:80", then listen on all available unicast and anycast addresses on the local system. The port must be a literal port number or a service name. The default address is :7357.
-log logfile
Write the server log to 'logfile', or to standard output if 'logfile' is "-". To suppress logging, set -logfile to /dev/null. By default, http-echo logs to stdout.
http-echo logs requests in a format similar to Common Log Format, including the request ID displayed in the response.
-set_prefix prefix
Use 'prefix' as the prefix for request headers that are used to set response headers. The default prefix is X-Set-.
-version
Print the version and exit.
### INSTALLATION
Building the binary requires an installation of gogitversion. Re-building README.md requires godoc and pandoc. See the links in SEE ALSO below.
To install the binary:
make install
To build the Docker image:
make container
See the Makefile for additional targets, useful for development.
### SEE ALSO
.
* source code repository: https://code.uplex.de/testing/http-echo
* gogitversion: https://github.com/slimhazard/gogitversion
* pandoc: https://pandoc.org/
### COPYRIGHT
Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung. All rights reserved
Author: Geoffrey Simmons &lt;geoffrey.simmons@uplex.de&gt;
See LICENSE
/*
* Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
// http-echo is an HTTP server that echoes all requests in the response.
//
// SYNOPSIS
//
// .
// http-echo [-address host:port] [-log logfile] [-set_prefix prefix]
// [-version]
//
// DESCRIPTON
//
// http-echo is an HTTP server that returns a brief summary of the
// request as well as the request header and body in the response
// body. It may also set response headers as specified in request
// headers that have a special prefix (default 'X-Set-') in the
// request header name.
//
// For example, if http-echo is listening at its default port 7357 on
// localhost:
//
// $ curl -d 'foo=bar&baz=quux' http://localhost:7357/foo/bar/baz
// Server address: 127.0.0.1:7357
// Server name: myhostname
// Date: 05/Apr/2019:23:37:11 +0200
// URI: /foo/bar/baz
// Request ID: 9566c74d10037c4d7bbb0407d1e2c649
//
// POST /foo/bar/baz HTTP/1.1
// Host: localhost:7357
// User-Agent: curl/7.52.1
// Content-Length: 16
// Accept: */*
// Content-Type: application/x-www-form-urlencoded
//
// foo=bar&baz=quux
//
// http-echo returns status 200 OK for every request that it receives,
// for any URL and request method.
//
// The response body begins with these five lines, followed by the
// request header and body:
//
// Server address: <address at which the request was received>
// Server name: <hostname on which http-echo is running>
// Date: <date/time at which the request was received>
// URI: <URL path>
// Request ID: <ID generated by http-echo for the request>
//
// Request headers with a special prefix, default 'X-Set-', may be used
// to set response headers. If the request has such a header, then the
// part of the header name after the prefix becomes the response header
// name, and the value of the request header becomes the value of the
// response header.
//
// There can be multiple headers with the "set" prefix in the request,
// all of which set a response header. If more than one "set" request
// header designates response headers with the same name, then
// multiple response headers with that name are set in the response.
//
// For example:
//
// # Using curl -I to show the response headers:
// $ curl -I -H 'X-Set-Foo: bar' -H 'X-Set-Baz: quux' http://localhost:7357/foo/bar/baz
// HTTP/1.1 200 OK
// Baz: quux
// Content-Type: text/plain
// Foo: bar
// Date: Fri, 05 Apr 2019 22:23:08 GMT
// Content-Length: 273
//
// # Set the same response header name more than once:
// $ curl -I -H 'X-Set-Foo: bar' -H 'X-Set-Foo: baz' http://localhost:7357/foo/bar/baz
// HTTP/1.1 200 OK
// Content-Type: text/plain
// Foo: bar
// Foo: baz
// Date: Fri, 05 Apr 2019 22:25:26 GMT
// Content-Length: 272
//
// OPTIONS
//
// http-echo may be used with these command-line flags:
//
// -address host:port
//
// Use 'host:port' as the address at which http-echo listens. The host
// must be a literal IP address or a host name that can be resolved to
// IP addresses. If the host is a literal IPv6 address, it must be
// enclosed in square brackets. If the host is empty or a literal
// unspecified IP address, as in ":80", "0.0.0.0:80" or "[::]:80",
// then listen on all available unicast and anycast addresses on the
// local system. The port must be a literal port number or a service
// name. The default address is :7357.
//
// -log logfile
//
// Write the server log to 'logfile', or to standard output if
// 'logfile' is "-". To suppress logging, set -logfile to
// /dev/null. By default, http-echo logs to stdout.
//
// http-echo logs requests in a format similar to Common Log Format,
// including the request ID displayed in the response.
//
// -set_prefix prefix
//
// Use 'prefix' as the prefix for request headers that are used to
// set response headers. The default prefix is X-Set-.
//
// -version
//
// Print the version and exit.
//
// INSTALLATION
//
// Building the binary requires an installation of
// gogitversion. Re-building README.md requires godoc and pandoc. See
// the links in SEE ALSO below.
//
// To install the binary:
//
// make install
//
// To build the Docker image:
//
// make container
//
// See the Makefile for additional targets, useful for development.
//
// SEE ALSO
//
// .
// * source code repository: https://code.uplex.de/testing/http-echo
// * gogitversion: https://github.com/slimhazard/gogitversion
// * pandoc: https://pandoc.org/
//
// COPYRIGHT
//
// Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung.
// All rights reserved
//
// Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
//
// See LICENSE
package main
/*
* Copyright (c) 2019 UPLEX Nils Goroll Systemoptimierung
* All rights reserved
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package main
//go:generate gogitversion -p main
import (
"encoding/hex"
"flag"
"fmt"
"log"
"math/rand"
"net"
"net/http"
"os"
"strings"
"time"
)
var (
hostname string
logger *log.Logger
address = flag.String("address", ":7357", "listen address")
logF = flag.String("log", "", "log file (default stdout)")
setPrefix = flag.String("set_prefix", "X-Set-",
"request header prefix for setting response headers")
versionF = flag.Bool("version", false, "show version and exit")
)
const tFormat = "02/Jan/2006:15:04:05 -0700"
func reqID() string {
bytes := make([]byte, 16)
rand.Read(bytes)
return hex.EncodeToString(bytes)
}
func reqLog(req *http.Request, t, id string) {
clientIP := req.RemoteAddr
if colon := strings.LastIndex(clientIP, ":"); colon != -1 {
clientIP = clientIP[:colon]
}
logger.Printf("%s - - [%s] \"%s %s %s\" 200 (%s)\n", clientIP,
t, req.Method, req.RequestURI, req.Proto, id)
}
func handle(resp http.ResponseWriter, req *http.Request) {
now := time.Now().Format(tFormat)
id := reqID()
respHdr := resp.Header()
respHdr.Set("Content-Type", "text/plain")
for reqHdr, vals := range req.Header {
if !strings.HasPrefix(reqHdr, *setPrefix) {
continue
}
newHdr := string([]byte(reqHdr)[len(*setPrefix):])
for _, val := range vals {
respHdr.Add(newHdr, val)
}
}
addrVal := req.Context().Value(http.LocalAddrContextKey)
if addrVal == nil {
fmt.Fprintln(resp, "Server address: unknown")
} else if addr, ok := addrVal.(net.Addr); !ok {
fmt.Fprintln(resp, "Server address: unknown")
} else {
fmt.Fprintln(resp, "Server address:", addr.String())
}
fmt.Fprintln(resp, "Server name:", hostname)
fmt.Fprintln(resp, "Date:", now)
fmt.Fprintln(resp, "URI:", req.RequestURI)
fmt.Fprintln(resp, "Request ID:", id)
fmt.Fprintln(resp)
req.Write(resp)
reqLog(req, now, id)
}
func main() {
var err error
flag.Parse()
if *versionF {
fmt.Println("http-echo version", version)
os.Exit(0)
}
out := os.Stdout
if *logF != "" && *logF != "-" {
if out, err = os.OpenFile(*logF,
os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644); err != nil {
log.Fatalf("%v", err)
}
}
logger = log.New(out, "", log.LstdFlags)
logger.Println("starting http-echo version", version)
if hostname, err = os.Hostname(); err != nil {
logger.Printf("cannot get hostname: %v", err)
hostname = "unknown"
}
mux := http.NewServeMux()
mux.HandleFunc("/", handle)
logger.Println("listening at:", *address)
logger.SetFlags(0)
logger.Fatal(http.ListenAndServe(*address, mux))
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment