Full Code of gophergala/ImgurGo for AI

master fedf337a57e2 cached
424 files
3.0 MB
820.2k tokens
8322 symbols
1 requests
Download .txt
Showing preview only (3,279K chars total). Download the full file or copy to clipboard to get everything.
Repository: gophergala/ImgurGo
Branch: master
Commit: fedf337a57e2
Files: 424
Total size: 3.0 MB

Directory structure:
gitextract_yns78iqd/

├── .buildpacks
├── .gitignore
├── .travis.yml
├── Dockerfile
├── Godeps/
│   ├── Godeps.json
│   └── Readme
├── LICENSE
├── Procfile
├── README.md
├── app.json
├── config/
│   ├── config.go
│   └── default.conf.json
├── docker/
│   ├── build_gm.sh
│   ├── conf.json
│   └── meme.traineddata
├── goclean.sh
├── imageprocessor/
│   ├── compresslosslessly.go
│   ├── exifstripper.go
│   ├── imageorienter.go
│   ├── imageprocessor.go
│   ├── imagescaler.go
│   ├── ocr.go
│   ├── ocr_test.go
│   ├── processorcommand/
│   │   ├── gm.go
│   │   ├── jpegtran.go
│   │   ├── ocrcommands.go
│   │   ├── optipng.go
│   │   ├── runner.go
│   │   └── stripmetadata.go
│   └── thumbType/
│       └── thumbType.go
├── imagestore/
│   ├── factory.go
│   ├── gcsstore.go
│   ├── hash.go
│   ├── localstore.go
│   ├── memorystore.go
│   ├── namepathmapper.go
│   ├── s3store.go
│   ├── store.go
│   └── storeobject.go
├── main.go
├── server/
│   ├── authenticator.go
│   ├── authenticator_test.go
│   ├── server.go
│   ├── server_test.go
│   └── stats.go
├── uploadedfile/
│   ├── thumbfile.go
│   └── uploadedfile.go
└── vendor/
    ├── github.com/
    │   ├── PagerDuty/
    │   │   └── godspeed/
    │   │       ├── .gitignore
    │   │       ├── .travis.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── async.go
    │   │       ├── events.go
    │   │       ├── godspeed.go
    │   │       ├── service_checks.go
    │   │       ├── shared.go
    │   │       └── stats.go
    │   ├── bradfitz/
    │   │   └── http2/
    │   │       ├── .gitignore
    │   │       ├── AUTHORS
    │   │       ├── CONTRIBUTORS
    │   │       ├── Dockerfile
    │   │       ├── HACKING
    │   │       ├── LICENSE
    │   │       ├── Makefile
    │   │       ├── README
    │   │       ├── buffer.go
    │   │       ├── errors.go
    │   │       ├── flow.go
    │   │       ├── frame.go
    │   │       ├── gotrack.go
    │   │       ├── h2i/
    │   │       │   ├── README.md
    │   │       │   └── h2i.go
    │   │       ├── headermap.go
    │   │       ├── hpack/
    │   │       │   ├── encode.go
    │   │       │   ├── hpack.go
    │   │       │   ├── huffman.go
    │   │       │   └── tables.go
    │   │       ├── http2.go
    │   │       ├── pipe.go
    │   │       ├── server.go
    │   │       ├── transport.go
    │   │       ├── write.go
    │   │       └── writesched.go
    │   ├── golang/
    │   │   ├── glog/
    │   │   │   ├── LICENSE
    │   │   │   ├── README
    │   │   │   ├── glog.go
    │   │   │   └── glog_file.go
    │   │   └── protobuf/
    │   │       ├── LICENSE
    │   │       └── proto/
    │   │           ├── Makefile
    │   │           ├── clone.go
    │   │           ├── decode.go
    │   │           ├── encode.go
    │   │           ├── equal.go
    │   │           ├── extensions.go
    │   │           ├── lib.go
    │   │           ├── message_set.go
    │   │           ├── pointer_reflect.go
    │   │           ├── pointer_unsafe.go
    │   │           ├── properties.go
    │   │           ├── proto3_proto/
    │   │           │   ├── proto3.pb.go
    │   │           │   └── proto3.proto
    │   │           ├── text.go
    │   │           └── text_parser.go
    │   ├── gorilla/
    │   │   ├── context/
    │   │   │   ├── .travis.yml
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── context.go
    │   │   │   └── doc.go
    │   │   └── mux/
    │   │       ├── .travis.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── doc.go
    │   │       ├── mux.go
    │   │       ├── regexp.go
    │   │       └── route.go
    │   ├── mitchellh/
    │   │   └── goamz/
    │   │       ├── LICENSE
    │   │       ├── aws/
    │   │       │   ├── attempt.go
    │   │       │   ├── aws.go
    │   │       │   └── client.go
    │   │       └── s3/
    │   │           ├── multi.go
    │   │           ├── s3.go
    │   │           ├── s3test/
    │   │           │   └── server.go
    │   │           └── sign.go
    │   ├── trustmaster/
    │   │   └── go-aspell/
    │   │       ├── README.md
    │   │       └── aspell.go
    │   └── vaughan0/
    │       └── go-ini/
    │           ├── LICENSE
    │           ├── README.md
    │           ├── ini.go
    │           └── test.ini
    ├── golang.org/
    │   └── x/
    │       ├── crypto/
    │       │   ├── LICENSE
    │       │   ├── PATENTS
    │       │   └── ssh/
    │       │       └── terminal/
    │       │           ├── terminal.go
    │       │           ├── util.go
    │       │           ├── util_bsd.go
    │       │           ├── util_linux.go
    │       │           └── util_windows.go
    │       ├── net/
    │       │   ├── LICENSE
    │       │   ├── PATENTS
    │       │   └── context/
    │       │       └── context.go
    │       └── oauth2/
    │           ├── .travis.yml
    │           ├── AUTHORS
    │           ├── CONTRIBUTING.md
    │           ├── CONTRIBUTORS
    │           ├── LICENSE
    │           ├── README.md
    │           ├── client_appengine.go
    │           ├── clientcredentials/
    │           │   └── clientcredentials.go
    │           ├── facebook/
    │           │   └── facebook.go
    │           ├── github/
    │           │   └── github.go
    │           ├── google/
    │           │   ├── appengine.go
    │           │   ├── appengine_hook.go
    │           │   ├── default.go
    │           │   ├── google.go
    │           │   └── sdk.go
    │           ├── internal/
    │           │   ├── oauth2.go
    │           │   ├── token.go
    │           │   └── transport.go
    │           ├── jws/
    │           │   └── jws.go
    │           ├── jwt/
    │           │   └── jwt.go
    │           ├── linkedin/
    │           │   └── linkedin.go
    │           ├── oauth2.go
    │           ├── odnoklassniki/
    │           │   └── odnoklassniki.go
    │           ├── paypal/
    │           │   └── paypal.go
    │           ├── token.go
    │           ├── transport.go
    │           └── vk/
    │               └── vk.go
    └── google.golang.org/
        ├── api/
        │   ├── LICENSE
        │   ├── bigquery/
        │   │   └── v2/
        │   │       ├── bigquery-api.json
        │   │       └── bigquery-gen.go
        │   ├── container/
        │   │   └── v1beta1/
        │   │       ├── container-api.json
        │   │       └── container-gen.go
        │   ├── googleapi/
        │   │   ├── googleapi.go
        │   │   ├── internal/
        │   │   │   └── uritemplates/
        │   │   │       ├── LICENSE
        │   │   │       ├── uritemplates.go
        │   │   │       └── utils.go
        │   │   ├── transport/
        │   │   │   └── apikey.go
        │   │   └── types.go
        │   ├── pubsub/
        │   │   └── v1beta2/
        │   │       ├── pubsub-api.json
        │   │       └── pubsub-gen.go
        │   └── storage/
        │       └── v1/
        │           ├── storage-api.json
        │           └── storage-gen.go
        ├── appengine/
        │   ├── .travis.yml
        │   ├── LICENSE
        │   ├── README.md
        │   ├── aetest/
        │   │   ├── doc.go
        │   │   ├── instance.go
        │   │   ├── instance_classic.go
        │   │   ├── instance_vm.go
        │   │   └── user.go
        │   ├── appengine.go
        │   ├── appengine_vm.go
        │   ├── blobstore/
        │   │   ├── blobstore.go
        │   │   └── read.go
        │   ├── capability/
        │   │   └── capability.go
        │   ├── channel/
        │   │   └── channel.go
        │   ├── cloudsql/
        │   │   ├── cloudsql.go
        │   │   ├── cloudsql_classic.go
        │   │   └── cloudsql_vm.go
        │   ├── cmd/
        │   │   ├── aebundler/
        │   │   │   └── aebundler.go
        │   │   └── aedeploy/
        │   │       └── aedeploy.go
        │   ├── datastore/
        │   │   ├── datastore.go
        │   │   ├── doc.go
        │   │   ├── key.go
        │   │   ├── load.go
        │   │   ├── metadata.go
        │   │   ├── prop.go
        │   │   ├── query.go
        │   │   ├── save.go
        │   │   └── transaction.go
        │   ├── delay/
        │   │   └── delay.go
        │   ├── demos/
        │   │   ├── guestbook/
        │   │   │   ├── app.yaml
        │   │   │   ├── guestbook.go
        │   │   │   ├── index.yaml
        │   │   │   └── templates/
        │   │   │       └── guestbook.html
        │   │   └── helloworld/
        │   │       ├── app.yaml
        │   │       └── helloworld.go
        │   ├── errors.go
        │   ├── file/
        │   │   └── file.go
        │   ├── identity.go
        │   ├── image/
        │   │   └── image.go
        │   ├── internal/
        │   │   ├── aetesting/
        │   │   │   └── fake.go
        │   │   ├── api.go
        │   │   ├── api_classic.go
        │   │   ├── api_common.go
        │   │   ├── app_id.go
        │   │   ├── app_identity/
        │   │   │   ├── app_identity_service.pb.go
        │   │   │   └── app_identity_service.proto
        │   │   ├── base/
        │   │   │   ├── api_base.pb.go
        │   │   │   └── api_base.proto
        │   │   ├── blobstore/
        │   │   │   ├── blobstore_service.pb.go
        │   │   │   └── blobstore_service.proto
        │   │   ├── capability/
        │   │   │   ├── capability_service.pb.go
        │   │   │   └── capability_service.proto
        │   │   ├── channel/
        │   │   │   ├── channel_service.pb.go
        │   │   │   └── channel_service.proto
        │   │   ├── datastore/
        │   │   │   ├── datastore_v3.pb.go
        │   │   │   └── datastore_v3.proto
        │   │   ├── identity.go
        │   │   ├── identity_classic.go
        │   │   ├── identity_vm.go
        │   │   ├── image/
        │   │   │   ├── images_service.pb.go
        │   │   │   └── images_service.proto
        │   │   ├── internal.go
        │   │   ├── log/
        │   │   │   ├── log_service.pb.go
        │   │   │   └── log_service.proto
        │   │   ├── mail/
        │   │   │   ├── mail_service.pb.go
        │   │   │   └── mail_service.proto
        │   │   ├── memcache/
        │   │   │   ├── memcache_service.pb.go
        │   │   │   └── memcache_service.proto
        │   │   ├── metadata.go
        │   │   ├── modules/
        │   │   │   ├── modules_service.pb.go
        │   │   │   └── modules_service.proto
        │   │   ├── net.go
        │   │   ├── regen.sh
        │   │   ├── remote_api/
        │   │   │   ├── remote_api.pb.go
        │   │   │   └── remote_api.proto
        │   │   ├── search/
        │   │   │   ├── search.pb.go
        │   │   │   └── search.proto
        │   │   ├── socket/
        │   │   │   ├── socket_service.pb.go
        │   │   │   └── socket_service.proto
        │   │   ├── system/
        │   │   │   ├── system_service.pb.go
        │   │   │   └── system_service.proto
        │   │   ├── taskqueue/
        │   │   │   ├── taskqueue_service.pb.go
        │   │   │   └── taskqueue_service.proto
        │   │   ├── transaction.go
        │   │   ├── urlfetch/
        │   │   │   ├── urlfetch_service.pb.go
        │   │   │   └── urlfetch_service.proto
        │   │   ├── user/
        │   │   │   ├── user_service.pb.go
        │   │   │   └── user_service.proto
        │   │   └── xmpp/
        │   │       ├── xmpp_service.pb.go
        │   │       └── xmpp_service.proto
        │   ├── log/
        │   │   ├── api.go
        │   │   └── log.go
        │   ├── mail/
        │   │   └── mail.go
        │   ├── memcache/
        │   │   └── memcache.go
        │   ├── module/
        │   │   └── module.go
        │   ├── namespace.go
        │   ├── remote_api/
        │   │   ├── client.go
        │   │   └── remote_api.go
        │   ├── runtime/
        │   │   └── runtime.go
        │   ├── search/
        │   │   ├── doc.go
        │   │   ├── field.go
        │   │   ├── search.go
        │   │   └── struct.go
        │   ├── socket/
        │   │   ├── doc.go
        │   │   ├── socket_classic.go
        │   │   └── socket_vm.go
        │   ├── taskqueue/
        │   │   └── taskqueue.go
        │   ├── timeout.go
        │   ├── urlfetch/
        │   │   └── urlfetch.go
        │   ├── user/
        │   │   ├── oauth.go
        │   │   ├── user.go
        │   │   ├── user_classic.go
        │   │   └── user_vm.go
        │   └── xmpp/
        │       └── xmpp.go
        ├── cloud/
        │   ├── .travis.yml
        │   ├── AUTHORS
        │   ├── CONTRIBUTING.md
        │   ├── CONTRIBUTORS
        │   ├── LICENSE
        │   ├── README.md
        │   ├── bigquery/
        │   │   ├── bigquery.go
        │   │   ├── copy_op.go
        │   │   ├── doc.go
        │   │   ├── error.go
        │   │   ├── extract_op.go
        │   │   ├── gcs.go
        │   │   ├── iterator.go
        │   │   ├── job.go
        │   │   ├── load_op.go
        │   │   ├── query.go
        │   │   ├── query_op.go
        │   │   ├── read_op.go
        │   │   ├── schema.go
        │   │   ├── service.go
        │   │   ├── table.go
        │   │   └── value.go
        │   ├── bigtable/
        │   │   ├── admin.go
        │   │   ├── bigtable.go
        │   │   ├── bttest/
        │   │   │   └── inmem.go
        │   │   ├── cmd/
        │   │   │   └── cbt/
        │   │   │       ├── cbt.go
        │   │   │       └── cbtdoc.go
        │   │   ├── doc.go
        │   │   ├── filter.go
        │   │   ├── internal/
        │   │   │   ├── cluster_data_proto/
        │   │   │   │   ├── bigtable_cluster_data.pb.go
        │   │   │   │   └── bigtable_cluster_data.proto
        │   │   │   ├── cluster_service_proto/
        │   │   │   │   ├── bigtable_cluster_service.pb.go
        │   │   │   │   ├── bigtable_cluster_service.proto
        │   │   │   │   ├── bigtable_cluster_service_messages.pb.go
        │   │   │   │   └── bigtable_cluster_service_messages.proto
        │   │   │   ├── data_proto/
        │   │   │   │   ├── bigtable_data.pb.go
        │   │   │   │   └── bigtable_data.proto
        │   │   │   ├── empty/
        │   │   │   │   ├── empty.pb.go
        │   │   │   │   └── empty.proto
        │   │   │   ├── regen.sh
        │   │   │   ├── service_proto/
        │   │   │   │   ├── bigtable_service.pb.go
        │   │   │   │   ├── bigtable_service.proto
        │   │   │   │   ├── bigtable_service_messages.pb.go
        │   │   │   │   └── bigtable_service_messages.proto
        │   │   │   ├── table_data_proto/
        │   │   │   │   ├── bigtable_table_data.pb.go
        │   │   │   │   └── bigtable_table_data.proto
        │   │   │   └── table_service_proto/
        │   │   │       ├── bigtable_table_service.pb.go
        │   │   │       ├── bigtable_table_service.proto
        │   │   │       ├── bigtable_table_service_messages.pb.go
        │   │   │       └── bigtable_table_service_messages.proto
        │   │   └── sample/
        │   │       └── search.go
        │   ├── cloud.go
        │   ├── compute/
        │   │   └── metadata/
        │   │       └── metadata.go
        │   ├── container/
        │   │   └── container.go
        │   ├── datastore/
        │   │   ├── datastore.go
        │   │   ├── errors.go
        │   │   ├── key.go
        │   │   ├── load.go
        │   │   ├── prop.go
        │   │   ├── query.go
        │   │   ├── save.go
        │   │   ├── time.go
        │   │   └── transaction.go
        │   ├── examples/
        │   │   ├── bigquery/
        │   │   │   ├── concat_table/
        │   │   │   │   └── main.go
        │   │   │   ├── load/
        │   │   │   │   └── main.go
        │   │   │   ├── query/
        │   │   │   │   └── main.go
        │   │   │   └── read/
        │   │   │       └── main.go
        │   │   ├── pubsub/
        │   │   │   └── cmdline/
        │   │   │       └── main.go
        │   │   └── storage/
        │   │       ├── appengine/
        │   │       │   ├── app.go
        │   │       │   └── app.yaml
        │   │       └── appenginevm/
        │   │           ├── app.go
        │   │           └── app.yaml
        │   ├── internal/
        │   │   ├── cloud.go
        │   │   ├── datastore/
        │   │   │   ├── datastore_v1.pb.go
        │   │   │   └── datastore_v1.proto
        │   │   └── testutil/
        │   │       └── context.go
        │   ├── key.json.enc
        │   ├── option.go
        │   ├── pubsub/
        │   │   └── pubsub.go
        │   └── storage/
        │       ├── acl.go
        │       ├── storage.go
        │       └── types.go
        └── grpc/
            ├── .travis.yml
            ├── CONTRIBUTING.md
            ├── LICENSE
            ├── PATENTS
            ├── README.md
            ├── benchmark/
            │   ├── benchmark.go
            │   ├── client/
            │   │   └── main.go
            │   ├── grpc_testing/
            │   │   ├── test.pb.go
            │   │   └── test.proto
            │   ├── server/
            │   │   └── main.go
            │   └── stats/
            │       ├── counter.go
            │       ├── histogram.go
            │       ├── stats.go
            │       ├── timeseries.go
            │       ├── tracker.go
            │       └── util.go
            ├── call.go
            ├── clientconn.go
            ├── codegen.sh
            ├── codes/
            │   ├── code_string.go
            │   └── codes.go
            ├── credentials/
            │   └── credentials.go
            ├── doc.go
            ├── examples/
            │   └── route_guide/
            │       ├── README.md
            │       ├── client/
            │       │   └── client.go
            │       ├── proto/
            │       │   ├── route_guide.pb.go
            │       │   └── route_guide.proto
            │       └── server/
            │           └── server.go
            ├── grpc-auth-support.md
            ├── grpclog/
            │   └── logger.go
            ├── interop/
            │   ├── client/
            │   │   └── client.go
            │   ├── grpc_testing/
            │   │   ├── test.pb.go
            │   │   └── test.proto
            │   └── server/
            │       └── server.go
            ├── metadata/
            │   └── metadata.go
            ├── rpc_util.go
            ├── server.go
            ├── stream.go
            ├── test/
            │   ├── codec_perf/
            │   │   ├── perf.pb.go
            │   │   └── perf.proto
            │   └── grpc_testing/
            │       ├── test.pb.go
            │       └── test.proto
            └── transport/
                ├── control.go
                ├── http2_client.go
                ├── http2_server.go
                ├── http_util.go
                └── transport.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .buildpacks
================================================
https://github.com/mcollina/heroku-buildpack-graphicsmagick
https://github.com/kr/heroku-buildpack-go.git


================================================
FILE: .gitignore
================================================
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so

# Folders
_obj
_test

# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out

*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*

_testmain.go

*.exe
*.test
*.prof

ImgurGo
tags

*.sw[o-p]

profile.cov


================================================
FILE: .travis.yml
================================================
sudo: required

services:
  - docker

before_install:
  - docker build -t imgur/mandible .

script:
  - docker run -e "COVERALLS_TOKEN=$COVERALLS_TOKEN" -e "TRAVIS_JOB_ID=$TRAVIS_JOB_ID" imgur/mandible /bin/sh -c "cd /go/src/github.com/Imgur/mandible && ./goclean.sh"


================================================
FILE: Dockerfile
================================================
FROM golang:1.8-stretch
RUN apt-get update && apt-get install -yqq aspell aspell-en libaspell-dev tesseract-ocr tesseract-ocr-eng libc6 optipng exiftool libjpeg-progs webp
ADD docker/build_gm.sh /tmp/build_gm.sh
RUN bash /tmp/build_gm.sh
ADD docker/meme.traineddata /usr/share/tesseract-ocr/tessdata/meme.traineddata
RUN mkdir -p /etc/mandible /tmp/imagestore
ENV MANDIBLE_CONF /etc/mandible/conf.json
ADD . /go/src/github.com/Imgur/mandible
WORKDIR /go/src/github.com/Imgur/mandible
RUN go get github.com/mattn/goveralls
RUN go get github.com/tools/godep
RUN godep restore
RUN godep go install -v .
CMD ["mandible"]


================================================
FILE: Godeps/Godeps.json
================================================
{
	"ImportPath": "github.com/Imgur/mandible",
	"GoVersion": "go1.5",
	"Packages": [
		"./..."
	],
	"Deps": [
		{
			"ImportPath": "github.com/bradfitz/http2",
			"Rev": "f8202bc903bda493ebba4aa54922d78430c2c42f"
		},
		{
			"ImportPath": "github.com/golang/glog",
			"Rev": "44145f04b68cf362d9c4df2182967c2275eaefed"
		},
		{
			"ImportPath": "github.com/golang/protobuf/proto",
			"Rev": "34a5f244f1c01cdfee8e60324258cfbb97a42aec"
		},
		{
			"ImportPath": "github.com/gorilla/context",
			"Rev": "215affda49addc4c8ef7e2534915df2c8c35c6cd"
		},
		{
			"ImportPath": "github.com/gorilla/mux",
			"Rev": "47e8f450ef38c857cdd922ec08862ca9d65a1c6d"
		},
		{
			"ImportPath": "github.com/mitchellh/goamz/aws",
			"Rev": "2441a8d0fab90553ec345cfdf3db24bb61ea61c3"
		},
		{
			"ImportPath": "github.com/mitchellh/goamz/s3",
			"Rev": "2441a8d0fab90553ec345cfdf3db24bb61ea61c3"
		},
		{
			"ImportPath": "github.com/trustmaster/go-aspell",
			"Rev": "b1cc0c2c49f83195f1708a1e6d23967d94817296"
		},
		{
			"ImportPath": "github.com/vaughan0/go-ini",
			"Rev": "a98ad7ee00ec53921f08832bc06ecf7fd600e6a1"
		},
		{
			"ImportPath": "golang.org/x/crypto/ssh/terminal",
			"Rev": "3760e016850398b85094c4c99e955b8c3dea5711"
		},
		{
			"ImportPath": "golang.org/x/net/context",
			"Rev": "84afb0af0050ae286aa9ced0c29383c2a866a925"
		},
		{
			"ImportPath": "golang.org/x/oauth2",
			"Rev": "b5adcc2dcdf009d0391547edc6ecbaff889f5bb9"
		},
		{
			"ImportPath": "google.golang.org/api/bigquery/v2",
			"Rev": "0610a35668fd6881bec389e74208f0df92010e96"
		},
		{
			"ImportPath": "google.golang.org/api/container/v1beta1",
			"Rev": "0610a35668fd6881bec389e74208f0df92010e96"
		},
		{
			"ImportPath": "google.golang.org/api/googleapi",
			"Rev": "0610a35668fd6881bec389e74208f0df92010e96"
		},
		{
			"ImportPath": "google.golang.org/api/pubsub/v1beta2",
			"Rev": "0610a35668fd6881bec389e74208f0df92010e96"
		},
		{
			"ImportPath": "google.golang.org/api/storage/v1",
			"Rev": "0610a35668fd6881bec389e74208f0df92010e96"
		},
		{
			"ImportPath": "google.golang.org/appengine",
			"Rev": "6bde959377a90acb53366051d7d587bfd7171354"
		},
		{
			"ImportPath": "google.golang.org/cloud",
			"Rev": "0b21ed5434dc279f2b8ea3c02dc69135600bbb8b"
		},
		{
			"ImportPath": "google.golang.org/grpc",
			"Rev": "d6f8134fd2e79a0a2a40f284d5552065fb6a8e3c"
		}
	]
}


================================================
FILE: Godeps/Readme
================================================
This directory tree is generated automatically by godep.

Please do not edit.

See https://github.com/tools/godep for more information.


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2015 Imgur, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: Procfile
================================================
web: ImgurGo


================================================
FILE: README.md
================================================
# mandible ![TravisStatus](https://travis-ci.org/Imgur/mandible.svg) [![Coverage Status](https://coveralls.io/repos/Imgur/mandible/badge.svg)](https://coveralls.io/r/Imgur/mandible)

A ready-to-deploy uploader that you can run on AWS EC2 or Heroku. It accepts an image via a REST interface and returns information about a file. Also, supports processing steps such as compression and thumbnail generation.


[![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy)


## Features:
Supported file types
- JPG
- PNG
- GIF

Pluggable storage layers
- S3
- Local

Pluggable authentication scheme
- Time-grant HMAC

Processing Steps:
- Compression
- Thumbnail generation

## Installation

### Docker

Pull down the mandible config file and edit it:

```
wget https://raw.githubusercontent.com/Imgur/mandible/master/config/default.conf.json -O ~/mandible/conf.json
```
```
vim ~/mandible/conf.json
```

To start mandible (port settings could change based on your conf.json):

```
docker run --name mandible -v ~/mandible:/etc/mandible -d -p 80:8080 imgur/mandible
```

To stop mandible:

```
docker stop mandible
```

To run it again:

```
docker run mandible
```
### (Optional) Authentication

- Set the following environment variable
    - AUTHENTICATION_HMAC_KEY

### S3 Storage Layer
Add the following to the `Stores` array in your conf.json file:

```
    {
        "Type" : "s3",
        "BucketName" : "",
        "AWSKey": "",
        "AWSSecret": "",
        "StoreRoot" : "",
        "Region" : "us-east-1",
        "NamePathRegex" : "",
        "NamePathMap" : "${ImageSize}/${ImageName}"
    }
```


## REST API:

Interfacing with mandible is extremely simple:

### Upload an image file:
`POST /file`

with the following multi-part/form-data
- ```image``` - file

---
### Upload an image from a URL:
`POST /url`

with the following multi-part/form-data
- ```image``` - string

---
### Upload an image from base64 data:
`POST /base64`

with the following multi-part/form-data
- ```image``` - image encoded as base64 data

---
### Thumbnail generation during upload:

**To generate thumbnails with an upload request, pass the following JSON as form-data, keyed under `thumbs`**

```javascript
{
    "name1": {
        "width": x,
        "height": y,
        "shape": ("square" | "thumb" | "circle")
    },
    "name2": {
        "width": x2,
        "height": y2,
        "shape": ("square" | "thumb" | "circle")
    },

    ...
}
```

Note: Square thumbnails don't preserve aspect ratio, whereas the 'thumb' type does

---
### On the fly thumbnail generation:
**this will return `content-type: image/...` and serve up a thumbnail.**

`GET /thumbnail`

with the following get parameters:
- ```uid``` - Unique ID of the image
- ```thumbs``` - JSON of the following format:
```javascript
{
    "name for the thumbnail": {
        "shape": ("square" | "thumb" | "circle" | "custom") // required
        "width": int,
        "height": int,
        "max_width": int,
        "max_height": int,
        "crop_gravity": string, // e.g. "nw" for north west of the image
        "crop_height": int,
        "crop_width": int,
        "quaity": int,
        "crop_ratio": string, // e.g. "2:1"
        "format": string, // one of: jpg, png, gif, webm,
        "nostore": bool, // if true, the resulting thumbnail won't be added to the backing storage
    }
}
```

---
### OCR endpoint
**Runs OCR on the given image and returns text**

`GET /ocr`

with the following get parameters:
- ```uid``` - Unique ID of the image

returns:
```Javascript
{
    "hash": string, //uid of the image
    "ocrtext": string // text returned from OCR
}
```

## Example usage (assuming localhost)

### URL Upload with thumbnails:

```
curl -i http://127.0.0.1:8080/url \
-d 'image=http://i.imgur.com/s9zxmYe.jpg' \
-d 'thumbs={"small": {"width": 20, "height": 20, "shape": "square"}, "profile": {"width": 50, "height": 50, "shape": "circle"}}'
```
### Response:

```javascript
{
    "data": {
        "width": 380,
        "height": 430,
        "link": "https://s3.amazonaws.com/gophergala/original/CUqU4If",
        "mime": "image/jpeg",
        "name": "",
        "size": 82199,
        "thumbs": {
            "profile":"https://s3.amazonaws.com/gophergala/t/CUqU4If/profile",
            "small": "https://s3.amazonaws.com/gophergala/t/CUqU4If/small"
        }
    },
    "status": 200,
    "success": true
}
```
### File Upload with thumbnails:

```
curl -i http://127.0.0.1:8080/file \
-F 'image=@/tmp/cat.gif' \
-F 'thumbs={"small": {"width": 20, "height": 20, "shape": "square"}}'
```
### Response:

```javascript
{
    "data": {
        "width": 354,
        "height": 200,
        "link": "https://s3.amazonaws.com/gophergala/original/L4ASjMX",
        "mime": "image/gif",
        "name": "cat.gif",
        "size": 3511100,
        "thumbs": {
            "small":"https://s3.amazonaws.com/gophergala/t/L4ASjMX/small"
        }
    },
    "status": 200,
    "success": true
}
```

### Authenticated upload

Uses HTTP headers `Authentication` and `X-Authentication-HMAC`. Generate HMACs by base64-encoding a JSON blob like below. [Example MAC generator](http://play.golang.org/p/3otGr8LBZt).
Supplying the client with the Authentication blob and MAC is out of scope for this project. In the future we will support symmetric and asymmetric encryption of the authentication blobs.

#### Request to my own account with proper authorization:

```
curl -i http://127.0.0.1:8080/user/1/url \
-d 'image=http://i.imgur.com/s9zxmYe.jpg' \
-H 'Authorization: {"user_id":1,"grant_time":"2010-06-01T00:00:00Z","grant_duration_sec":31536000}' \
-H 'X-Authorization-HMAC: tCtGb04n4nvd/94+Xd6vAx9+pJw51ZmX1vH7E+BlTtc='
```

#### Response:
```javascript
{"data":{"link":"/tmp/original/J/a/Jafq9IH","mime":"image/jpeg","name":"s9zxmYe.jpg","hash":"Jafq9IH","size":81881,"width":380,"height":430,"ocrtext":"change\np.roject .\n\n  \n  \n\n  forg@ot to git p.ull before\n- .-+#~+):,-r,ad)q..,i,ng so/ /","thumbs":{},"user_id":"\u0001"},"status":200,"success":true}
```

#### Request to other user's account:

```
curl -i http://127.0.0.1:8080/user/2/url \
-d 'image=http://i.imgur.com/s9zxmYe.jpg' \
-H 'Authorization: {"user_id":1,"grant_time":"2010-06-01T00:00:00Z","grant_duration_sec":31536000}' \
-H 'X-Authorization-HMAC: tCtGb04n4nvd/94+Xd6vAx9+pJw51ZmX1vH7E+BlTtc='
```

#### Response:
```
HTTP/1.1 401 Unauthorized
Date: Mon, 08 Jun 2015 21:04:41 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8
```


#### HMAC prevents account forgery

```
curl -i http://127.0.0.1:8080/user/1/url \
-d 'image=http://i.imgur.com/s9zxmYe.jpg' \
-H 'Authorization: {"user_id":1,"grant_time":"2010-06-01T00:00:00Z","grant_duration_sec":31536000}' \
-H 'X-Authorization-HMAC: foobar'
```

#### Response:
```javascript
HTTP/1.1 401 Unauthorized
Date: Mon, 08 Jun 2015 21:04:41 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8
```

## Contributing

The easiest way to develop on this project is to use the built-in docker image. We are using the Go 1.5 vendor experiment, which means if
you import a package you must vendor the source code into this repository using Godep.


================================================
FILE: app.json
================================================
{
  "name": "ImgurGo",
  "description": "An easy Heroku image uploading service",
  "repository": "https://github.com/gophergala/ImgurGo",
  "env": {
      "BUILDPACK_URL": "https://github.com/ddollar/heroku-buildpack-multi",
      "IMGUR_GO_CONF": "config/default.conf.json",
      "S3_BUCKET": {
          "description": "AWS S3 Bucket",
          "required": false
      },
      "AWS_ACCESS_KEY_ID": {
          "description": "AWS Acess Key ID",
          "required": false
      },
      "AWS_SECRET_ACCESS_KEY": {
          "description": "AWS Acess Key Secret",
          "required": false
      }
  }
}


================================================
FILE: config/config.go
================================================
package config

import (
	"encoding/json"
	"fmt"
	"os"
)

type Configuration struct {
	MaxFileSize     int64
	HashLength      int
	UserAgent       string
	Stores          []map[string]string
	Port            int
	DatadogEnabled  bool
	DatadogHostname string
}

func NewConfiguration(path string) *Configuration {
	file, err := os.Open(path)

	if err != nil {
		fmt.Printf("Error opening config file!")
		os.Exit(-1)
	}

	decoder := json.NewDecoder(file)
	configuration := &Configuration{}
	err = decoder.Decode(configuration)

	if err != nil {
		fmt.Println("Error loading config file: ", err)
	}

	return configuration
}


================================================
FILE: config/default.conf.json
================================================
{
    "Port": 8080,
    "MaxFileSize": 20971520,
    "HashLength": 7,
    "UserAgent": "ImgurGo (https://github.com/gophergala/ImgurGo)",
    "Stores" : [
        {
            "Type" : "s3",
            "BucketName" : "",
            "AWSKey": "",
            "AWSSecret": "",
            "StoreRoot" : "",
            "Region" : "us-east-1",
            "NamePathRegex" : "",
            "NamePathMap" : "${ImageSize}/${ImageName}"
        },
        {
            "Type" : "gcs",
            "BucketName" : "",
            "StoreRoot" : "",
            "AppID" : "",
            "KeyFile" : "appid.json",
            "NamePathRegex" : "",
            "NamePathMap" : "${ImageSize}/${ImageName}"
        },
        {
            "Type" : "local",
            "StoreRoot": "/Users/jarvis/imagestore",
            "NamePathRegex" : "^([a-zA-Z0-9])([a-zA-Z0-9]).*",
            "NamePathMap" : "${ImageSize}/${1}/${2}/${ImageName}"
        }
    ],
    "DatadogEnabled": false,
    "DatadogHostname": "127.0.0.1"
}


================================================
FILE: docker/build_gm.sh
================================================
#!/bin/bash

apt-get install -y libjpeg-dev liblcms2-dev libwmf-dev libx11-dev libsm-dev libice-dev libxext-dev x11proto-core-dev libxml2-dev libfreetype6-dev libexif-dev libbz2-dev libtiff-dev libjbig-dev zlib1g-dev libpng-dev libwebp-dev ghostscript gsfonts autotools-dev transfig sharutils libltdl-dev mercurial cmake
wget "http://www.ece.uvic.ca/~frodo/jasper/software/jasper-2.0.12.tar.gz" -O jasper.tar.gz
mkdir jasper && tar -xvzf jasper.tar.gz -C jasper --strip-components 1 && cd jasper
mkdir BUILD && cd BUILD && cmake -DCMAKE_INSTALL_PREFIX=/usr    \
      -DCMAKE_BUILD_TYPE=Release     \
      -DCMAKE_SKIP_INSTALL_RPATH=YES \
      -DCMAKE_INSTALL_DOCDIR=/usr/share/doc/jasper-2.0.10 \
      ..  &&
make
make install
cd ../.. && rm -rf jasper jasper.tar.gz
hg clone http://hg.code.sf.net/p/graphicsmagick/code GM
cd GM
hg update -r tip
CC="gcc" CFLAGS="-fopenmp -Wall -g -fno-strict-aliasing -O3 -Wall -pthread" CPPFLAGS="-I/usr/include/X11 -I/usr/include/freetype2 -I/usr/include/libxml2" CXX="g++" CXXFLAGS="-Wall -g -fno-strict-aliasing -O3 -pthread" LDFLAGS="-L/usr/lib/X11 -L/usr/lib/x86_64-linux-gnu" LIBS="-ljbig -lwebp -llcms2 -ltiff -lfreetype -ljpeg -lpng16 -lwmflite -lXext -lSM -lICE -lX11 -llzma -lbz2 -lxml2 -lz -lm -lgomp -lpthread" ./configure  '--build' 'x86_64-linux-gnu' '--enable-shared' '--enable-static' '--enable-libtool-verbose' '--prefix=/usr' '--mandir=${prefix}/share/man' '--infodir=${prefix}/share/info' '--docdir=${prefix}/share/doc/graphicsmagick' '--with-gs-font-dir=/usr/share/fonts/type1/gsfonts' '--with-x' '--x-includes=/usr/include/X11' '--x-libraries=/usr/lib/X11' '--with-included-ltdl' '--with-modules' '--enable-openmp-slow' '--without-dps' '--without-frozenpaths' '--with-webp' '--with-perl' '--with-perl-options=INSTALLDIRS=vendor' '--enable-quantum-library-names' '--with-quantum-depth=16' 'build_alias=x86_64-linux-gnu' 'CFLAGS=-Wall -g -fno-strict-aliasing -O3' 'LDFLAGS=' 'CXXFLAGS=-Wall -g -fno-strict-aliasing -O3'
make
make install
cd .. && rm -rf GM


================================================
FILE: docker/conf.json
================================================
{
    "Port": 8080,
    "MaxFileSize": 20971520,
    "HashLength": 7,
    "UserAgent": "Mandible (https://github.com/Imgur/Mandible)",
    "Stores" : [
        {
            "Type" : "local",
            "StoreRoot": "/tmp/imagestore",
            "NamePathRegex" : "^([a-zA-Z0-9])([a-zA-Z0-9]).*",
            "NamePathMap" : "${ImageSize}/${1}/${2}/${ImageName}"
        }
    ]
}


================================================
FILE: goclean.sh
================================================
#!/bin/bash
# The script does automatic checking on a Go package and its sub-packages, including:
# 1. gofmt         (http://golang.org/cmd/gofmt/)
# 2. goimports     (https://github.com/bradfitz/goimports)
# 3. golint        (https://github.com/golang/lint)
# 4. go vet        (http://golang.org/cmd/vet)
# 5. race detector (http://blog.golang.org/race-detector)
# 6. test coverage (http://blog.golang.org/cover)

export GO15VENDOREXPERIMENT=1

set -e

PROJECTS="./uploadedfile ./server ./imageprocessor ./imagestore ./config ."

# Automatic checks
test -z "$(gofmt -l -w .     | tee /dev/stderr)"
# test -z "$(goimports -l -w . | tee /dev/stderr)"
# test -z "$(golint .          | tee /dev/stderr)"
godep go vet $PROJECTS
godep go test -race $PROJECTS

# Run test coverage on each subdirectories and merge the coverage profile.

echo "mode: count" > profile.cov

# Standard go tooling behavior is to ignore dirs with leading underscors
for dir in $PROJECTS
do
if ls $dir/*.go &> /dev/null; then
    godep go test -covermode=count -coverprofile=$dir/profile.tmp $dir
    if [ -f $dir/profile.tmp ]
    then
        cat $dir/profile.tmp | tail -n +2 >> profile.cov
        rm $dir/profile.tmp
    fi
fi
done

godep go tool cover -func profile.cov

# This is breaking travis-ci. Disabling it for now.
# [ ${COVERALLS_TOKEN} ] && goveralls -coverprofile=profile.cov -service travis-ci -repotoken $COVERALLS_TOKEN


================================================
FILE: imageprocessor/compresslosslessly.go
================================================
package imageprocessor

import (
	"errors"

	"github.com/Imgur/mandible/imageprocessor/processorcommand"
	"github.com/Imgur/mandible/uploadedfile"
)

type CompressLosslessly struct{}

func (this *CompressLosslessly) Process(image *uploadedfile.UploadedFile) error {
	if image.IsJpeg() {
		return this.compressJpeg(image)
	}

	if image.IsPng() {
		return this.compressPng(image)
	}

	if image.IsGif() {
		return nil
	}

	return errors.New("Unsuported filetype")
}

func (this *CompressLosslessly) String() string {
	return "Lossy compressor"
}

func (this *CompressLosslessly) compressPng(image *uploadedfile.UploadedFile) error {
	filename, err := processorcommand.Optipng(image.GetPath())
	if err != nil {
		return err
	}

	image.SetPath(filename)

	return nil
}

func (this *CompressLosslessly) compressJpeg(image *uploadedfile.UploadedFile) error {
	filename, err := processorcommand.Jpegtran(image.GetPath())
	if err != nil {
		return err
	}

	image.SetPath(filename)

	return nil
}


================================================
FILE: imageprocessor/exifstripper.go
================================================
package imageprocessor

import (
	"github.com/Imgur/mandible/imageprocessor/processorcommand"
	"github.com/Imgur/mandible/uploadedfile"
)

type ExifStripper struct{}

func (this *ExifStripper) Process(image *uploadedfile.UploadedFile) error {
	if !image.IsJpeg() {
		return nil
	}

	err := processorcommand.StripMetadata(image.GetPath())
	if err != nil {
		return err
	}

	return nil
}

func (this *ExifStripper) String() string {
	return "EXIF stripper"
}


================================================
FILE: imageprocessor/imageorienter.go
================================================
package imageprocessor

import (
	"github.com/Imgur/mandible/imageprocessor/processorcommand"
	"github.com/Imgur/mandible/uploadedfile"
)

type ImageOrienter struct{}

func (this *ImageOrienter) Process(image *uploadedfile.UploadedFile) error {
	filename, err := processorcommand.FixOrientation(image.GetPath())
	if err != nil {
		return err
	}

	image.SetPath(filename)

	return nil
}

func (this *ImageOrienter) String() string {
	return "Image orienter"
}


================================================
FILE: imageprocessor/imageprocessor.go
================================================
package imageprocessor

import (
	"fmt"
	"strings"

	"github.com/Imgur/mandible/config"
	"github.com/Imgur/mandible/uploadedfile"
)

type ProcessType interface {
	Process(image *uploadedfile.UploadedFile) error
	String() string
}

type multiProcessType []ProcessType

func (this multiProcessType) Process(image *uploadedfile.UploadedFile) error {
	for _, processor := range this {
		err := processor.Process(image)
		if err != nil {
			return fmt.Errorf("Error multiprocessing on %s: %s", processor.String(), err.Error())
		}
	}

	return nil
}

func (this multiProcessType) String() string {
	processes := make([]string, 0)
	for _, p := range this {
		processes = append(processes, p.String())
	}
	return "Multiple processes <" + strings.Join(processes, ", ") + ">"
}

type asyncProcessType []ProcessType

func (this asyncProcessType) Process(image *uploadedfile.UploadedFile) error {
	errs := make(chan error, len(this))

	for _, processor := range this {
		go func(p ProcessType) {
			err := p.Process(image)
			if err != nil {
				errs <- fmt.Errorf("Error asynchronously processing on %s: %s", p.String(), err.Error())
			} else {
				errs <- nil
			}
		}(processor)
	}

	for i := 0; i < len(this); i++ {
		select {
		case err := <-errs:
			if err != nil {
				return err
			}
		}
	}

	return nil
}

func (this asyncProcessType) String() string {
	processes := make([]string, 0)
	for _, p := range this {
		processes = append(processes, p.String())
	}
	return "Async processes <" + strings.Join(processes, ", ") + ">"
}

type ImageProcessor struct {
	processor ProcessType
}

func (this *ImageProcessor) Run(image *uploadedfile.UploadedFile) error {
	return this.processor.Process(image)
}

type ImageProcessorStrategy func(*config.Configuration, *uploadedfile.UploadedFile) (*ImageProcessor, error)

// Just do nothing to the file after it's uploaded...
var PassthroughStrategy = func(cfg *config.Configuration, file *uploadedfile.UploadedFile) (*ImageProcessor, error) {
	return &ImageProcessor{multiProcessType{}}, nil
}

var ThumbnailStrategy = func(cfg *config.Configuration, file *uploadedfile.UploadedFile) (*ImageProcessor, error) {
	processor := asyncProcessType{}
	for _, t := range file.GetThumbs() {
		processor = append(processor, t)
	}

	return &ImageProcessor{processor}, nil
}

var EverythingStrategy = func(cfg *config.Configuration, file *uploadedfile.UploadedFile) (*ImageProcessor, error) {
	size, err := file.FileSize()
	if err != nil {
		return &ImageProcessor{}, err
	}

	processor := multiProcessType{}
	processor = append(processor, &ImageOrienter{})
	processor = append(processor, &CompressLosslessly{})
	processor = append(processor, &ExifStripper{})

	if size > cfg.MaxFileSize {
		processor = append(processor, &ImageScaler{cfg.MaxFileSize})
	}

	async := asyncProcessType{}

	async = append(async, DuelOCRStratagy())
	for _, t := range file.GetThumbs() {
		async = append(async, t)
	}

	if len(async) > 0 {
		processor = append(processor, async)
	}

	return &ImageProcessor{processor}, nil
}


================================================
FILE: imageprocessor/imagescaler.go
================================================
package imageprocessor

import (
	"errors"

	"github.com/Imgur/mandible/imageprocessor/processorcommand"
	"github.com/Imgur/mandible/uploadedfile"
)

type ImageScaler struct {
	targetSize int64
}

func (this *ImageScaler) Process(image *uploadedfile.UploadedFile) error {
	switch image.GetMime() {
	case "image/jpeg", "image/jpg":
		return this.scaleJpeg(image)
	case "image/png":
		return this.scalePng(image)
	case "image/gif":
		return this.scaleGif(image)
	}

	return errors.New("Unsuported filetype")
}

func (this *ImageScaler) String() string {
	return "Image scaler"
}

func (this *ImageScaler) scalePng(image *uploadedfile.UploadedFile) error {
	filename, err := processorcommand.ConvertToJpeg(image.GetPath())
	if err != nil {
		return err
	}

	image.SetPath(filename)
	image.SetMime("image/jpeg")
	return this.scaleJpeg(image)
}

func (this *ImageScaler) scaleJpeg(image *uploadedfile.UploadedFile) error {
	filename, err := processorcommand.Quality(image.GetPath(), 90)
	if err != nil {
		return err
	}

	image.SetPath(filename)
	size, err := image.FileSize()
	if size < this.targetSize {
		return nil
	}

	filename, err = processorcommand.Quality(image.GetPath(), 70)
	if err != nil {
		return err
	}

	image.SetPath(filename)
	size, err = image.FileSize()
	if size < this.targetSize {
		return nil
	}

	percent := 90
	if (size - this.targetSize) >= (15 * 1024 * 1024) {
		percent = 30
	} else if (size - this.targetSize) >= (10 * 1024 * 1024) {
		percent = 40
	} else if (size - this.targetSize) >= (5 * 1024 * 1024) {
		percent = 60
	}

	for {
		filename, err = processorcommand.ResizePercent(image.GetPath(), percent)
		if err != nil {
			return err
		}

		image.SetPath(filename)
		size, err := image.FileSize()
		if err != nil {
			return err
		} else if size == 0 || percent < 10 {
			return errors.New("Could not scale image to desired filesize")
		} else if size < this.targetSize {
			return nil
		}

		percent -= 10
	}
}

func (this *ImageScaler) scaleGif(image *uploadedfile.UploadedFile) error {
	return errors.New("Unimplimented")
}


================================================
FILE: imageprocessor/ocr.go
================================================
package imageprocessor

import (
	"github.com/Imgur/mandible/imageprocessor/processorcommand"
	"github.com/Imgur/mandible/uploadedfile"

	"log"
)

type OCRRunner struct {
	Command processorcommand.OCRCommand
}

func (this *OCRRunner) Process(image *uploadedfile.UploadedFile) error {
	result, err := this.Command.Run(image.GetPath())
	if err != nil {
		log.Printf("Error running OCR: %s", err.Error())
		return err
	}

	image.SetOCRText(result.Text)

	return nil
}

func (this *OCRRunner) String() string {
	return "OCR runner"
}

var DuelOCRStratagy = func() *OCRRunner {
	multi := processorcommand.MultiOCRCommand{}
	multi = append(multi, processorcommand.NewMemeOCR())
	multi = append(multi, processorcommand.NewStandardOCR())

	return &OCRRunner{multi}
}

var StandardOCRStratagy = func() *OCRRunner {
	return &OCRRunner{processorcommand.NewStandardOCR()}
}

var MemeOCRStratagy = func() *OCRRunner {
	return &OCRRunner{processorcommand.NewMemeOCR()}
}


================================================
FILE: imageprocessor/ocr_test.go
================================================
package imageprocessor

import (
	"errors"
	"io"
	"io/ioutil"
	"os"
	"testing"

	"github.com/Imgur/mandible/uploadedfile"
)

func TestStandardOCR(t *testing.T) {
	image, err := getUploadedFileObject()
	if err != nil {
		t.Fatalf("Could not initialize standard OCR test")
	}
	defer image.Clean()

	ocrStratagy := StandardOCRStratagy()
	ocrStratagy.Process(image)

	if image.GetOCRText() != "hello" {
		t.Fatalf("Did not get proper standard OCR text back %s != hello", image.GetOCRText())
	}
}

func getUploadedFileObject() (*uploadedfile.UploadedFile, error) {
	filename, err := copyTestImage("testdata/ocrtestimage.png")
	if err != nil {
		return nil, err
	}

	image, err := uploadedfile.NewUploadedFile("ocrtestimage.png", filename, nil)
	if err != nil {
		return nil, errors.New("Could not initialize standard OCR test")
	}

	return image, nil
}

func copyTestImage(filename string) (string, error) {
	uploadFile, err := os.Open(filename)
	if err != nil {
		return "", err
	}
	defer uploadFile.Close()

	tmpFile, err := ioutil.TempFile(os.TempDir(), "image")
	if err != nil {
		return "", errors.New("Unable to write to /tmp")
	}
	defer tmpFile.Close()

	_, err = io.Copy(tmpFile, uploadFile)
	if err != nil {
		return "", err
	}

	return tmpFile.Name(), nil
}


================================================
FILE: imageprocessor/processorcommand/gm.go
================================================
package processorcommand

import (
	"fmt"

	"github.com/Imgur/mandible/imageprocessor/thumbType"
)

const GM_COMMAND = "gm"

func ConvertToJpeg(filename string) (string, error) {
	outfile := fmt.Sprintf("%s_jpg", filename)

	args := []string{
		"convert",
		filename,
		"-flatten",
		"JPEG:" + outfile,
	}

	err := runProcessorCommand(GM_COMMAND, args)
	if err != nil {
		return "", err
	}

	return outfile, nil
}

func FixOrientation(filename string) (string, error) {
	outfile := fmt.Sprintf("%s_ort", filename)

	args := []string{
		"convert",
		filename,
		"-auto-orient",
		outfile,
	}

	err := runProcessorCommand(GM_COMMAND, args)
	if err != nil {
		return "", err
	}

	return outfile, nil
}

func Quality(filename string, quality int) (string, error) {
	outfile := fmt.Sprintf("%s_q", filename)

	args := []string{
		"convert",
		filename,
		"-quality",
		fmt.Sprintf("%d", quality),
		"-density",
		"72x72",
		outfile,
	}

	err := runProcessorCommand(GM_COMMAND, args)
	if err != nil {
		return "", err
	}

	return outfile, nil
}

func ResizePercent(filename string, percent int) (string, error) {
	outfile := fmt.Sprintf("%s_rp", filename)

	args := []string{
		"convert",
		filename,
		"-resize",
		fmt.Sprintf("%d%%", percent),
		outfile,
	}

	err := runProcessorCommand(GM_COMMAND, args)
	if err != nil {
		return "", err
	}

	return outfile, nil
}

func SquareThumb(filename, name string, size int, quality int, format thumbType.ThumbType) (string, error) {
	outfile := fmt.Sprintf("%s_%s", filename, name)

	args := []string{
		"convert",
		fmt.Sprintf("%s[0]", filename),
		"-resize",
		fmt.Sprintf("%dx%d^", size, size),
		"-gravity",
		"center",
		"-crop",
		fmt.Sprintf("%dx%d+0+0", size, size),
		"-density",
		"72x72",
		"-unsharp",
		"0.5",
	}

	if quality >= 0 {
		args = append(args,
			"-quality",
			fmt.Sprintf("%d", quality),
		)
	}

	args = append(args, fmt.Sprintf("%s:%s", format.ToString(), outfile))

	err := runProcessorCommand(GM_COMMAND, args)
	if err != nil {
		return "", err
	}

	return outfile, nil
}

func Thumb(filename, name string, width, height int, quality int, format thumbType.ThumbType) (string, error) {
	outfile := fmt.Sprintf("%s_%s", filename, name)

	args := []string{
		"convert",
		fmt.Sprintf("%s[0]", filename),
		"-resize",
		fmt.Sprintf("%dx%d>", width, height),
		"-density",
		"72x72",
	}

	if quality >= 0 {
		args = append(args,
			"-quality",
			fmt.Sprintf("%d", quality),
		)
	}

	args = append(args, fmt.Sprintf("%s:%s", format.ToString(), outfile))

	err := runProcessorCommand(GM_COMMAND, args)
	if err != nil {
		return "", err
	}

	return outfile, nil
}

func CircleThumb(filename, name string, width int, quality int, format thumbType.ThumbType) (string, error) {
	outfile := fmt.Sprintf("%s_%s", filename, name)

	filename, err := SquareThumb(filename, name, width, quality, format)
	if err != nil {
		return "", err
	}

	args := []string{
		"convert",
		"-size",
		fmt.Sprintf("%dx%d", width, width),
		"xc:none",
		"-fill",
		filename,
		"-quality",
		"83",
		"-density",
		"72x72",
		"-draw",
		fmt.Sprintf("circle %d,%d %d,1", width/2, width/2, width/2),
	}

	if quality >= 0 {
		args = append(args,
			"-quality",
			fmt.Sprintf("%d", quality),
		)
	}

	args = append(args, fmt.Sprintf("PNG:%s", outfile))

	err = runProcessorCommand(GM_COMMAND, args)
	if err != nil {
		return "", err
	}

	return outfile, nil
}

func CustomThumb(filename, name string, width, height int, cropGravity string, cropWidth, cropHeight, quality int, format thumbType.ThumbType) (string, error) {
	outfile := fmt.Sprintf("%s_%s", filename, name)

	args := []string{
		"convert",
		fmt.Sprintf("%s[0]", filename),
		"-resize",
		fmt.Sprintf("%dx%d^", width, height),
		"-density",
		"72x72",
	}

	if quality != -1 {
		args = append(args,
			"-quality",
			fmt.Sprintf("%d", quality),
		)
	}

	if cropGravity != "" {
		args = append(args,
			"-gravity",
			fmt.Sprintf("%s", cropGravity),
			"-crop",
			fmt.Sprintf("%dx%d+0+0", cropWidth, cropHeight),
		)
	}

	args = append(args, fmt.Sprintf("%s:%s", format.ToString(), outfile))
	err := runProcessorCommand(GM_COMMAND, args)
	if err != nil {
		return "", err
	}

	return outfile, nil
}

func Full(filename string, name string, quality int, format thumbType.ThumbType) (string, error) {
	outfile := fmt.Sprintf("%s_%s", filename, name)

	args := []string{
		"convert",
		fmt.Sprintf("%s[0]", filename),
		"-density",
		"72x72",
	}

	if quality >= 0 {
		args = append(args,
			"-quality",
			fmt.Sprintf("%d", quality),
		)
	}

	args = append(args, fmt.Sprintf("%s:%s", format.ToString(), outfile))

	err := runProcessorCommand(GM_COMMAND, args)
	if err != nil {
		return "", err
	}

	return outfile, nil
}


================================================
FILE: imageprocessor/processorcommand/jpegtran.go
================================================
package processorcommand

import (
	"fmt"
)

func Jpegtran(filename string) (string, error) {
	outfile := fmt.Sprintf("%s_opti", filename)

	args := []string{
		"-copy",
		"all",
		"-optimize",
		"-outfile",
		outfile,
		filename,
	}

	err := runProcessorCommand("jpegtran", args)
	if err != nil {
		return "", err
	}

	return outfile, nil
}


================================================
FILE: imageprocessor/processorcommand/ocrcommands.go
================================================
package processorcommand

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
	"strings"

	"github.com/trustmaster/go-aspell"
)

type OCRResult struct {
	Type string
	Text string
}

func newOCRResult(ocrType string, result string) *OCRResult {
	return &OCRResult{
		ocrType,
		result,
	}
}

func (this *OCRResult) removeNonWords() {
	blob := this.Text

	speller, err := aspell.NewSpeller(map[string]string{
		"lang": "en_US",
	})
	if err != nil {
		fmt.Printf("Error: %s", err.Error())
		return
	}
	defer speller.Delete()

	singleCharWords := regexp.MustCompile("(a|i)")
	numberRegex := regexp.MustCompile("\\d{3,}")
	wordRegexp := regexp.MustCompile("\\b(\\w+)\\b")
	words := wordRegexp.FindAllString(blob, -1)

	str := ""

	for _, word := range words {
		if numberRegex.MatchString(word) {
			str += " " + word
		} else if len(word) == 1 {
			if singleCharWords.MatchString(word) {
				str += " " + word
			}
		} else if speller.Check(word) {
			str += " " + word
		}
	}

	this.Text = strings.TrimSpace(str)
}

func (this *OCRResult) wordCount(blob string) int {
	word_regexp := regexp.MustCompile("\\b(\\w+)\\b")
	words := word_regexp.FindAllString(blob, -1)

	// don't let single char words count towards the overal word count. Gets thrown off by poor OCR results
	count := 0
	for _, word := range words {
		if len(word) > 1 {
			count++
		}
	}

	return count
}

type MultiOCRCommand []OCRCommand

func (this MultiOCRCommand) Run(image string) (*OCRResult, error) {
	results := make(chan *OCRResult, len(this))
	errs := make(chan error, len(this))

	for _, command := range this {
		go func(c OCRCommand) {
			k, err := c.Run(image)
			if err != nil {
				errs <- err
				return
			}
			results <- k
		}(command)
	}

	max := -1
	var best *OCRResult

	for i := 0; i < len(this); i++ {
		select {
		case result := <-results:
			result.removeNonWords()
			count := result.wordCount(result.Text)

			if count > max {
				best = result
				max = count
			}

		case err := <-errs:
			return nil, err
		}
	}

	// Return the average, same as before.
	return best, nil
}

type OCRCommand interface {
	Run(image string) (*OCRResult, error)
}

type MemeOCR struct {
	name string
}

func NewMemeOCR() *MemeOCR {
	return &MemeOCR{
		"MemeOCR",
	}
}

func (this *MemeOCR) Run(image string) (*OCRResult, error) {
	imageTif := fmt.Sprintf("%s_meme.jpg", image)
	outText := fmt.Sprintf("%s_meme", image)
	inImage := fmt.Sprintf("%s[0]", image)
	preprocessingArgs := []string{"convert", inImage, "-resize", "400%", "-fill", "black", "-fuzz", "10%", "+matte", "-matte", "-transparent", "white", imageTif}
	tesseractArgs := []string{"-l", "meme", imageTif, outText}

	err := runProcessorCommand(GM_COMMAND, preprocessingArgs)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Meme preprocessing command failed with error = %v", err))
	}
	defer os.Remove(imageTif)

	err = runProcessorCommand("tesseract", tesseractArgs)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Meme tesseract command failed with error = %v", err))
	}
	defer os.Remove(outText + ".txt")

	text, err := ioutil.ReadFile(outText + ".txt")
	if err != nil {
		return nil, err
	}

	result := strings.ToLower(strings.TrimSpace(string(text[:])))

	return newOCRResult(this.name, result), nil
}

type StandardOCR struct {
	name string
}

func NewStandardOCR() *StandardOCR {
	return &StandardOCR{
		"StandardOCR",
	}
}

func (this *StandardOCR) Run(image string) (*OCRResult, error) {
	imageTif := fmt.Sprintf("%s_standard.jpg", image)
	outText := fmt.Sprintf("%s_standard", image)
	inImage := fmt.Sprintf("%s[0]", image)
	preprocessingArgs := []string{"convert", inImage, "-resize", "400%", "-type", "Grayscale", imageTif}
	tesseractArgs := []string{"-l", "eng", imageTif, outText}

	err := runProcessorCommand(GM_COMMAND, preprocessingArgs)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Standard preprocessing command failed with error = %v", err))
	}
	defer os.Remove(imageTif)

	err = runProcessorCommand("tesseract", tesseractArgs)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Standard tesseract command failed with error = %v", err))
	}
	defer os.Remove(outText + ".txt")

	text, err := ioutil.ReadFile(outText + ".txt")
	if err != nil {
		return nil, err
	}

	result := strings.ToLower(strings.TrimSpace(string(text[:])))

	return newOCRResult(this.name, result), nil
}


================================================
FILE: imageprocessor/processorcommand/optipng.go
================================================
package processorcommand

import (
	"fmt"
)

func Optipng(filename string) (string, error) {
	outfile := fmt.Sprintf("%s_opi", filename)

	args := []string{
		"-fix",
		"-out",
		outfile,
		filename,
	}

	err := runProcessorCommand("optipng", args)
	if err != nil {
		return "", err
	}

	return outfile, nil
}


================================================
FILE: imageprocessor/processorcommand/runner.go
================================================
package processorcommand

import (
	"bytes"
	"errors"
	"log"
	"os/exec"
	"time"
)

func runProcessorCommand(command string, args []string) error {
	cmd := exec.Command(command, args...)

	var out bytes.Buffer
	var stderr bytes.Buffer
	cmd.Stdout = &out
	cmd.Stderr = &stderr

	cmd.Start()

	cmdDone := make(chan error, 1)
	go func() {
		cmdDone <- cmd.Wait()
	}()

	select {
	case <-time.After(time.Duration(60) * time.Second):
		killCmd(cmd)
		<-cmdDone
		return errors.New("Command timed out")
	case err := <-cmdDone:
		if err != nil {
			log.Println(stderr.String())
		}

		return err
	}
}

func killCmd(cmd *exec.Cmd) {
	if err := cmd.Process.Kill(); err != nil {
		log.Printf("Failed to kill command: %v", err)
	}
}


================================================
FILE: imageprocessor/processorcommand/stripmetadata.go
================================================
package processorcommand

func StripMetadata(filename string) error {
	args := []string{
		"-all=",
		"--icc_profile:all",
		"-overwrite_original",
		filename,
	}

	err := runProcessorCommand("exiftool", args)
	if err != nil {
		return err
	}

	return nil
}


================================================
FILE: imageprocessor/thumbType/thumbType.go
================================================
package thumbType

type ThumbType int

const (
	UNKNOWN ThumbType = iota
	JPG
	PNG
	GIF
	WEBP
)

func (this ThumbType) ToString() string {
	switch this {
	case JPG:
		return "JPG"
	case PNG:
		return "PNG"
	case GIF:
		return "GIF"
	case WEBP:
		return "WEBP"
	default:
		return "UNKNOWN"
	}
}

func FromMime(mime string) ThumbType {
	switch mime {
	case "image/jpeg":
		return JPG
	case "image/png":
		return PNG
	case "image/gif":
		return GIF
	case "image/webp":
		return WEBP
	default:
		return UNKNOWN
	}
}

func FromString(format string) ThumbType {
	switch format {
	case "jpg":
		return JPG
	case "jpeg":
		return JPG
	case "png":
		return PNG
	case "gif":
		return GIF
	case "webp":
		return WEBP
	default:
		return UNKNOWN
	}
}


================================================
FILE: imagestore/factory.go
================================================
package imagestore

import (
	"io/ioutil"
	"log"

	"github.com/Imgur/mandible/config"
	"github.com/mitchellh/goamz/aws"
	"github.com/mitchellh/goamz/s3"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	gcloud "google.golang.org/cloud"
	gcs "google.golang.org/cloud/storage"
)

type Factory struct {
	conf *config.Configuration
}

func NewFactory(conf *config.Configuration) *Factory {
	return &Factory{conf}
}

func (this *Factory) NewImageStores() ImageStore {
	stores := MultiImageStore{}
	var store ImageStore

	for _, configWrapper := range this.conf.Stores {
		switch configWrapper["Type"] {
		case "s3":
			store = this.NewS3ImageStore(configWrapper)
			stores = append(stores, store)
		case "gcs":
			store = this.NewGCSImageStore(configWrapper)
			stores = append(stores, store)
		case "local":
			store = this.NewLocalImageStore(configWrapper)
			stores = append(stores, store)
		case "memory":
			store = NewInMemoryImageStore()
			stores = append(stores, store)
		default:
			log.Fatalf("Unsupported store %s", configWrapper["Type"])
		}
	}

	if len(this.conf.Stores) == 1 {
		return store
	}

	// return a MultiImageStore type if more then 1 store was specified in the config
	return stores
}

func (this *Factory) NewS3ImageStore(conf map[string]string) ImageStore {
	bucket := conf["BucketName"]

	auth, err := aws.GetAuth(conf["AWSKey"], conf["AWSSecret"])
	if err != nil {
		log.Fatal(err)
	}

	client := s3.New(auth, aws.Regions[conf["Region"]])
	mapper := NewNamePathMapper(conf["NamePathRegex"], conf["NamePathMap"])

	return NewS3ImageStore(
		bucket,
		conf["StoreRoot"],
		client,
		mapper,
	)
}

func (this *Factory) NewGCSImageStore(conf map[string]string) ImageStore {
	jsonKey, err := ioutil.ReadFile(conf["KeyFile"])
	if err != nil {
		log.Fatal(err)
	}
	cloudConf, err := google.JWTConfigFromJSON(
		jsonKey,
		gcs.ScopeFullControl,
	)
	if err != nil {
		log.Fatal(err)
	}

	bucket := conf["BucketName"]

	ctx := gcloud.NewContext(conf["AppID"], cloudConf.Client(oauth2.NoContext))
	mapper := NewNamePathMapper(conf["NamePathRegex"], conf["NamePathMap"])

	return NewGCSImageStore(
		ctx,
		bucket,
		conf["StoreRoot"],
		mapper,
	)
}

func (this *Factory) NewLocalImageStore(conf map[string]string) ImageStore {
	mapper := NewNamePathMapper(conf["NamePathRegex"], conf["NamePathMap"])
	return NewLocalImageStore(conf["StoreRoot"], mapper)
}

func (this *Factory) NewStoreObject(id string, mime string, size string) *StoreObject {
	return &StoreObject{
		Id:       id,
		MimeType: mime,
		Size:     size,
	}
}

func (this *Factory) NewHashGenerator(store ImageStore) *HashGenerator {
	hashGen := &HashGenerator{
		make(chan string),
		this.conf.HashLength,
		store,
	}

	hashGen.init()
	return hashGen
}


================================================
FILE: imagestore/gcsstore.go
================================================
package imagestore

import (
	"io"
	"io/ioutil"
	"log"
	"os"

	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

type GCSImageStore struct {
	ctx            context.Context
	bucketName     string
	storeRoot      string
	namePathMapper *NamePathMapper
}

func NewGCSImageStore(ctx context.Context, bucket string, root string, mapper *NamePathMapper) *GCSImageStore {
	return &GCSImageStore{
		ctx:            ctx,
		bucketName:     bucket,
		storeRoot:      root,
		namePathMapper: mapper,
	}
}

func (this *GCSImageStore) Exists(obj *StoreObject) (bool, error) {
	_, err := storage.StatObject(this.ctx, this.bucketName, this.toPath(obj))
	if err != nil {
		return false, err
	}
	return true, nil
}

func (this *GCSImageStore) Save(src string, obj *StoreObject) (*StoreObject, error) {
	srcFd, err := os.Open(src)
	if err != nil {
		return nil, err
	}
	defer srcFd.Close()

	data, err := ioutil.ReadAll(srcFd)
	if err != nil {
		log.Printf("error on read file: %s", err)
		return nil, err
	}

	wc := storage.NewWriter(this.ctx, this.bucketName, this.toPath(obj))
	wc.ContentType = obj.MimeType
	if _, err := wc.Write(data); err != nil {
		log.Printf("error on write data: %s", err)
		return nil, err
	}
	if err := wc.Close(); err != nil {
		log.Printf("error on close writer: %s", err)
		return nil, err
	}

	obj.Url = "https://storage.googleapis.com/" + this.bucketName + "/" + this.toPath(obj)
	return obj, nil
}

func (this *GCSImageStore) Get(obj *StoreObject) (io.ReadCloser, error) {
	reader, err := storage.NewReader(this.ctx, this.bucketName, this.toPath(obj))
	if err != nil {
		log.Printf("error on read file: %s", err)
		return nil, err
	}

	return reader, nil
}

func (this *GCSImageStore) String() string {
	return "GCSStore"
}

func (this *GCSImageStore) toPath(obj *StoreObject) string {
	if this.storeRoot != "" {
		return this.storeRoot + "/" + this.namePathMapper.mapToPath(obj)
	}
	return this.namePathMapper.mapToPath(obj)
}


================================================
FILE: imagestore/hash.go
================================================
package imagestore

import (
	"crypto/rand"
	"log"
)

// Provides a continuous stream of random image "hashes" of a fixed length that is unique (does not exist in the store).
type HashGenerator struct {
	hashGetter chan string
	length     int
	store      ImageStore
}

func (this *HashGenerator) init() {
	go func() {
		storeObj := &StoreObject{
			"",
			"",
			"original",
			"",
		}

		for {
			str := ""

			for len(str) < this.length {
				c := 10
				bArr := make([]byte, c)
				_, err := rand.Read(bArr)
				if err != nil {
					log.Println("error:", err)
					break
				}

				for _, b := range bArr {
					if len(str) == this.length {
						break
					}

					/**
					 * Each byte will be in [0, 256), but we only care about:
					 *
					 * [48, 57]     0-9
					 * [65, 90]     A-Z
					 * [97, 122]    a-z
					 *
					 * Which means that the highest bit will always be zero, since the last byte with high bit
					 * zero is 01111111 = 127 which is higher than 122. Lower our odds of having to re-roll a byte by
					 * dividing by two (right bit shift of 1).
					 */

					b = b >> 1

					// The byte is any of        0-9                  A-Z                      a-z
					byteIsAllowable := (b >= 48 && b <= 57) || (b >= 65 && b <= 90) || (b >= 97 && b <= 122)

					if byteIsAllowable {
						str += string(b)
					}
				}

			}

			storeObj.Id = str

			exists, _ := this.store.Exists(storeObj)
			if !exists {
				this.hashGetter <- str
			}
		}
	}()
}

func (this *HashGenerator) Get() string {
	return <-this.hashGetter
}


================================================
FILE: imagestore/localstore.go
================================================
package imagestore

import (
	"io"
	"os"
	"path"
)

// A LocalImageStore stores images on the local disk.
type LocalImageStore struct {
	storeRoot      string
	namePathMapper *NamePathMapper
}

func NewLocalImageStore(root string, mapper *NamePathMapper) *LocalImageStore {
	return &LocalImageStore{
		storeRoot:      root,
		namePathMapper: mapper,
	}
}

func (this *LocalImageStore) Exists(obj *StoreObject) (bool, error) {
	if _, err := os.Stat(this.toPath(obj)); os.IsNotExist(err) {
		return false, err
	}

	return true, nil
}

func (this *LocalImageStore) Save(src string, obj *StoreObject) (*StoreObject, error) {
	srcFd, err := os.Open(src)
	if err != nil {
		return nil, err
	}
	defer srcFd.Close()

	// open output file
	this.createParent(obj)
	fo, err := os.Create(this.toPath(obj))
	if err != nil {
		return nil, err
	}

	defer fo.Close()

	_, err = io.Copy(fo, srcFd)
	if err != nil {
		return nil, err
	}

	obj.Url = this.toPath(obj)
	return obj, nil
}

func (this *LocalImageStore) Get(obj *StoreObject) (io.ReadCloser, error) {
	reader, err := os.Open(this.toPath(obj))
	if err != nil {
		return nil, err
	}

	return reader, nil
}

func (this *LocalImageStore) String() string {
	return "LocalStore"
}

func (this *LocalImageStore) createParent(obj *StoreObject) {
	path := path.Dir(this.toPath(obj))

	if _, err := os.Stat(path); os.IsNotExist(err) {
		os.MkdirAll(path, 0777)
	}
}

func (this *LocalImageStore) toPath(obj *StoreObject) string {
	return this.storeRoot + "/" + this.namePathMapper.mapToPath(obj)
}


================================================
FILE: imagestore/memorystore.go
================================================
package imagestore

import (
	"errors"
	"io"
	"io/ioutil"
	"os"
	"strings"
	"sync"
)

type InMemoryImageStore struct {
	files map[string]string // name -> contents
	rw    sync.Mutex
}

func NewInMemoryImageStore() *InMemoryImageStore {
	return &InMemoryImageStore{
		files: make(map[string]string),
		rw:    sync.Mutex{},
	}
}

func (this *InMemoryImageStore) Exists(obj *StoreObject) (bool, error) {
	this.rw.Lock()

	_, ok := this.files[obj.Id]

	this.rw.Unlock()

	return ok, nil
}

func (this *InMemoryImageStore) Save(src string, obj *StoreObject) (*StoreObject, error) {
	srcFd, err := os.Open(src)
	if err != nil {
		return nil, err
	}
	defer srcFd.Close()

	data, err := ioutil.ReadAll(srcFd)
	if err != nil {
		return nil, err
	}

	this.rw.Lock()
	this.files[obj.Id] = string(data)
	this.rw.Unlock()

	return obj, nil
}

func (this *InMemoryImageStore) Get(obj *StoreObject) (io.ReadCloser, error) {
	this.rw.Lock()
	data, ok := this.files[obj.Id]
	this.rw.Unlock()

	if !ok {
		return nil, errors.New("File doesn't exist")
	}

	reader := strings.NewReader(data)
	readCloser := ioutil.NopCloser(reader)
	return readCloser, nil
}

func (this *InMemoryImageStore) String() string {
	return "InMemoryStore"
}


================================================
FILE: imagestore/namepathmapper.go
================================================
package imagestore

import (
	"regexp"
	"strings"
)

type NamePathMapper struct {
	regex   *regexp.Regexp
	replace string
}

func NewNamePathMapper(expr string, mapping string) *NamePathMapper {
	var r *regexp.Regexp
	if len(expr) > 0 {
		r = regexp.MustCompile(expr)
	}

	return &NamePathMapper{
		r,
		mapping,
	}
}

func (this *NamePathMapper) mapToPath(obj *StoreObject) string {
	repl := strings.Replace(this.replace, "${ImageName}", obj.Id, -1)
	repl = strings.Replace(repl, "${ImageSize}", obj.Size, -1)

	if this.regex != nil {
		return this.regex.ReplaceAllString(obj.Id, repl)
	}

	return repl
}


================================================
FILE: imagestore/s3store.go
================================================
package imagestore

import (
	"io"
	"os"

	"github.com/mitchellh/goamz/s3"
)

type S3ImageStore struct {
	bucketName     string
	storeRoot      string
	client         *s3.S3
	namePathMapper *NamePathMapper
}

func NewS3ImageStore(bucket string, root string, client *s3.S3, mapper *NamePathMapper) *S3ImageStore {
	return &S3ImageStore{
		bucketName:     bucket,
		storeRoot:      root,
		client:         client,
		namePathMapper: mapper,
	}
}

func (this *S3ImageStore) Exists(obj *StoreObject) (bool, error) {
	bucket := this.client.Bucket(this.bucketName)
	response, err := bucket.Head(this.toPath(obj))
	if err != nil {
		return false, err
	}

	return (response.StatusCode == 200), nil
}

func (this *S3ImageStore) Save(src string, obj *StoreObject) (*StoreObject, error) {
	srcFd, err := os.Open(src)
	if err != nil {
		return nil, err
	}
	defer srcFd.Close()

	bucket := this.client.Bucket(this.bucketName)

	stats, err := srcFd.Stat()
	if err != nil {
		return nil, err
	}

	err = bucket.PutReader(this.toPath(obj), srcFd, stats.Size(), obj.MimeType, s3.BucketOwnerFull)
	if err != nil {
		return nil, err
	}

	obj.Url = bucket.URL(this.toPath(obj))
	return obj, nil
}

func (this *S3ImageStore) Get(obj *StoreObject) (io.ReadCloser, error) {
	bucket := this.client.Bucket(this.bucketName)
	data, err := bucket.GetReader(this.toPath(obj))
	if err != nil {
		return nil, err
	}

	return data, nil
}

func (this *S3ImageStore) String() string {
	return "S3Store"
}

func (this *S3ImageStore) toPath(obj *StoreObject) string {
	return this.storeRoot + "/" + this.namePathMapper.mapToPath(obj)
}


================================================
FILE: imagestore/store.go
================================================
package imagestore

import (
	"fmt"
	"io"
)

type ImageStore interface {
	Save(src string, obj *StoreObject) (*StoreObject, error)
	Exists(obj *StoreObject) (bool, error)
	Get(obj *StoreObject) (io.ReadCloser, error)
	String() string
}

type MultiImageStore []ImageStore

func (this MultiImageStore) Save(src string, obj *StoreObject) (*StoreObject, error) {
	errs := make(chan error, len(this))

	for _, store := range this {
		go func(s ImageStore) {
			_, err := s.Save(src, obj)
			if err != nil {
				errs <- fmt.Errorf("Error asynchronously saving image on %s: %s", s.String(), err.Error())
			} else {
				errs <- nil
			}
		}(store)
	}

	for i := 0; i < len(this); i++ {
		select {
		case err := <-errs:
			if err != nil {
				return nil, err
			}
		}
	}

	return obj, nil
}

func (this MultiImageStore) Exists(obj *StoreObject) (bool, error) {
	errs := make(chan error, len(this))
	results := make(chan bool, len(this))

	for _, store := range this {
		go func(s ImageStore) {
			r, err := s.Exists(obj)
			if err != nil {
				errs <- fmt.Errorf("Error asynchronously proving existance for image on %s: %s", s.String(), err.Error())
			} else {
				results <- r
			}
		}(store)
	}

	for i := 0; i < len(this); i++ {
		select {
		case err := <-errs:
			if err != nil {
				return false, err
			}
		case r := <-results:
			if r == true {
				return true, nil
			}
		}
	}

	return false, nil
}

func (this MultiImageStore) Get(obj *StoreObject) (io.ReadCloser, error) {
	errs := make(chan error, len(this))
	results := make(chan io.ReadCloser, 1)
	done := make(chan bool, 1)

	for _, store := range this {
		go func(s ImageStore) {
			r, err := s.Get(obj)
			if err != nil {
				errs <- fmt.Errorf("Error asynchronously getting image on %s: %s", s.String(), err.Error())
			} else {
				select {
				case done <- true:
					results <- r
				default:
					r.Close()
				}
			}
		}(store)
	}

	var err error

	for i := 0; i < len(this); i++ {
		select {
		case r := <-results:
			return r, nil
		case err = <-errs:
		}
	}

	return nil, err
}

func (this MultiImageStore) String() string {
	str := ""

	for _, store := range this {
		str += store.String()
		str += " "
	}

	return str
}


================================================
FILE: imagestore/storeobject.go
================================================
package imagestore

type StorableObject interface {
	GetPath() string
}

type StoreObject struct {
	Id       string // Unique identifier
	MimeType string // i.e. image/jpg
	Size     string // i.e. thumb
	Url      string // if publicly available
}

func (this *StoreObject) Store(s StorableObject, store ImageStore) error {
	path := s.GetPath()

	obj, err := store.Save(path, this)
	if err != nil {
		return err
	}

	this.Url = obj.Url

	return nil
}


================================================
FILE: main.go
================================================
package main

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

	mandibleConf "github.com/Imgur/mandible/config"
	processors "github.com/Imgur/mandible/imageprocessor"
	mandible "github.com/Imgur/mandible/server"
)

func main() {
	configFile := os.Getenv("MANDIBLE_CONF")

	config := mandibleConf.NewConfiguration(configFile)

	var server *mandible.Server
	var stats mandible.RuntimeStats

	if config.DatadogEnabled {
		var err error
		stats, err = mandible.NewDatadogStats(config.DatadogHostname)
		if err != nil {
			log.Printf("Invalid Datadog Hostname: %s", config.DatadogHostname)
			os.Exit(1)
		}
		log.Println("Stats init success")
	} else {
		stats = &mandible.DiscardStats{}
	}

	if os.Getenv("AUTHENTICATION_HMAC_KEY") != "" {
		key := []byte(os.Getenv("AUTHENTICATION_HMAC_KEY"))
		auth := mandible.NewHMACAuthenticatorSHA256(key)
		server = mandible.NewAuthenticatedServer(config, processors.EverythingStrategy, auth, stats)
	} else {
		server = mandible.NewServer(config, processors.EverythingStrategy, stats)
	}

	muxer := http.NewServeMux()
	server.Configure(muxer)

	port := fmt.Sprintf(":%d", server.Config.Port)

	log.Printf("Listening on Port: %s", port)

	stats.LogStartup()
	http.ListenAndServe(port, muxer)
}


================================================
FILE: server/authenticator.go
================================================
package server

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"errors"
	"hash"
	"net/http"
	"time"
)

var (
	ErrNoAuthentication = errors.New("No authentication scheme was configured.")
	ErrEmptyAuth        = errors.New("Empty or missing authentication header.")
	ErrNoGrantTime      = errors.New("No grant time specified in the authentication grant.")
	ErrExpiredGrant     = errors.New("The authentication grant has expired.")
	ErrMACMismatch      = errors.New("The provided message authentication code is invalid for the given message.")
)

type AuthenticatedUser struct {
	UserID               string    `json:"user_id"`
	GrantTime            time.Time `json:"grant_time"`
	GrantDurationSeconds int64     `json:"grant_duration_sec"`
}

type Authenticator interface {
	GetUser(*http.Request) (*AuthenticatedUser, error)
}

type PassthroughAuthenticator struct{}

func (auth *PassthroughAuthenticator) GetUser(req *http.Request) (*AuthenticatedUser, error) {
	return nil, ErrNoAuthentication
}

type HMACAuthenticator struct {
	key []byte
	h   func() hash.Hash
	now time.Time
}

func (auth *HMACAuthenticator) SetTime(t time.Time) {
	auth.now = t
}

func NewHMACAuthenticatorSHA256(key []byte) *HMACAuthenticator {
	return &HMACAuthenticator{
		key: key,
		h:   sha256.New,
	}
}

func (auth *HMACAuthenticator) GetUser(req *http.Request) (*AuthenticatedUser, error) {
	authHeader := []byte(req.Header.Get("Authorization"))
	userProvidedHmacBase64 := req.Header.Get("X-Authorization-HMAC")

	if len(authHeader) == 0 || userProvidedHmacBase64 == "" {
		return nil, ErrEmptyAuth
	}

	userProvidedHmac, _ := base64.StdEncoding.DecodeString(userProvidedHmacBase64)

	macWriter := hmac.New(auth.h, auth.key)
	macWriter.Write(authHeader)
	expectedMac := macWriter.Sum(nil)

	if hmac.Equal(expectedMac, userProvidedHmac) {
		var authUser AuthenticatedUser
		err := json.Unmarshal(authHeader, &authUser)
		// Valid JSON but no shared values will unmarshal to the zero valued authenticated user; only pass back
		// a non-zero-valued authenticated user
		if err == nil && authUser.UserID != "" {
			if authUser.GrantTime.IsZero() {
				return nil, ErrNoGrantTime
			} else if authUser.GrantTime.Add(time.Duration(authUser.GrantDurationSeconds) * time.Second).Before(auth.now) {
				return nil, ErrExpiredGrant
			} else {
				return &authUser, nil
			}
		}
	}

	return nil, ErrMACMismatch
}


================================================
FILE: server/authenticator_test.go
================================================
package server

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"net/http"
	"testing"
	"time"
)

func TestPassthroughAuthenticatorAlwaysReturnsNilUser(t *testing.T) {
	req, _ := http.NewRequest("POST", "http://127.0.0.1/user/123/url", nil)

	authenticator := &PassthroughAuthenticator{}
	user, err := authenticator.GetUser(req)
	if user != nil {
		t.Fatalf("Expected authenticator of the passthrough authenticator to be nil, instead %+v", user)
	}
	if err != ErrNoAuthentication {
		t.Fatalf("Unexpected error: %s", err.Error())
	}
}

func TestHMACAuthenticatorOnValidRequest(t *testing.T) {
	message := AuthenticatedUser{
		UserID:               "123",
		GrantTime:            time.Now(),
		GrantDurationSeconds: 365 * 24 * 3600,
	}
	messageBytes, _ := json.Marshal(&message)
	messageMacWriter := hmac.New(sha256.New, []byte("foobar"))
	messageMacWriter.Write(messageBytes)
	messageMac := base64.StdEncoding.EncodeToString(messageMacWriter.Sum(nil))

	req, _ := http.NewRequest("POST", "http://127.0.0.1/user/123/url", nil)

	req.Header.Set("Authorization", string(messageBytes))
	req.Header.Set("X-Authorization-HMAC", string(messageMac))

	authenticator := NewHMACAuthenticatorSHA256([]byte("foobar"))
	authenticator.SetTime(time.Now())
	user, err := authenticator.GetUser(req)
	if user == nil {
		t.Fatalf("Expected authenticator of of a valid response to not return nil")
	}
	if err != nil {
		t.Fatalf("Unexpected error: %s", err.Error())
	}
}

func TestHMACAuthenticatorOnEmptyHeader(t *testing.T) {
	req, _ := http.NewRequest("POST", "http://127.0.0.1/user/123/url", nil)

	req.Header.Set("Authorization", "")

	authenticator := NewHMACAuthenticatorSHA256([]byte("foobar"))
	user, err := authenticator.GetUser(req)
	if user != nil {
		t.Fatalf("Expected authenticator with no auth response to return nil")
	}
	if err != ErrEmptyAuth {
		t.Fatalf("Unexpected error: %s", err.Error())
	}
}

func TestHMACAuthenticatorOnInvalidRequest(t *testing.T) {
	message := AuthenticatedUser{
		UserID:               "123",
		GrantTime:            time.Now(),
		GrantDurationSeconds: 365 * 24 * 3600,
	}
	messageBytes, _ := json.Marshal(&message)
	// wrong key!
	messageMacWriter := hmac.New(sha256.New, []byte("jklfdsjklfsdjklfdsjklfsdjklfsd"))
	messageMacWriter.Write(messageBytes)
	messageMac := base64.StdEncoding.EncodeToString(messageMacWriter.Sum(nil))

	req, _ := http.NewRequest("POST", "http://127.0.0.1/user/123/url", nil)

	req.Header.Set("Authorization", string(messageBytes))
	req.Header.Set("X-Authorization-HMAC", string(messageMac))

	authenticator := NewHMACAuthenticatorSHA256([]byte("foobar"))
	authenticator.SetTime(time.Now())
	user, err := authenticator.GetUser(req)
	if user != nil {
		t.Fatalf("Expected authenticator of of an invalid response to return nil")
	}
	if err != ErrMACMismatch {
		t.Fatalf("Unexpected error: %s", err.Error())
	}
}

func TestHMACAuthenticatorOnExpiredGrant(t *testing.T) {
	grantedTime := time.Now()
	requestTime := time.Now().Add(time.Hour)
	message := AuthenticatedUser{
		UserID:               "123",
		GrantTime:            grantedTime,
		GrantDurationSeconds: 5,
	}
	messageBytes, _ := json.Marshal(&message)
	messageMacWriter := hmac.New(sha256.New, []byte("foobar"))
	messageMacWriter.Write(messageBytes)
	messageMac := base64.StdEncoding.EncodeToString(messageMacWriter.Sum(nil))

	req, _ := http.NewRequest("POST", "http://127.0.0.1/user/123/url", nil)

	req.Header.Set("Authorization", string(messageBytes))
	req.Header.Set("X-Authorization-HMAC", string(messageMac))

	authenticator := NewHMACAuthenticatorSHA256([]byte("foobar"))
	authenticator.SetTime(requestTime)

	user, err := authenticator.GetUser(req)
	if user != nil {
		t.Fatalf("Expected authenticator of of an invalid response to return nil")
	}
	if err != ErrExpiredGrant {
		t.Fatalf("Unexpected error: %s", err.Error())
	}
}


================================================
FILE: server/server.go
================================================
package server

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"strings"
	"time"

	"github.com/gorilla/mux"

	"github.com/Imgur/mandible/config"
	"github.com/Imgur/mandible/imageprocessor"
	"github.com/Imgur/mandible/imagestore"
	"github.com/Imgur/mandible/uploadedfile"
)

type Server struct {
	Config            *config.Configuration
	HTTPClient        *http.Client
	ImageStore        imagestore.ImageStore
	hashGenerator     *imagestore.HashGenerator
	processorStrategy imageprocessor.ImageProcessorStrategy
	authenticator     Authenticator
	stats             RuntimeStats
}

type ServerResponse struct {
	Error   string      `json:"error,omitempty"`
	Data    interface{} `json:"data,omitempty"`
	Status  int         `json:"status"`
	Success *bool       `json:"success"` // the empty value is the nil pointer, because this is a computed property
}

func (resp *ServerResponse) Write(w http.ResponseWriter, s RuntimeStats) {
	respBytes, _ := resp.json()

	if resp.Status >= http.StatusBadRequest {
		log.Println(fmt.Sprintf("HTTP error: %d -- %s", resp.Status, resp.Error))
		s.Error(resp.Status)
	}

	w.WriteHeader(resp.Status)
	w.Header().Set("Content-Type", "application/json")
	w.Write(respBytes)
}

// The success property is a computed property on the response status
// This can't implement the MarshalJSON() interface sadly because it would be recursive
func (resp *ServerResponse) json() ([]byte, error) {
	var success bool
	success = (resp.Status == http.StatusOK)
	resp.Success = &success
	bytes, err := json.Marshal(resp)
	resp.Success = nil
	return bytes, err
}

type ImageResponse struct {
	Link    string                 `json:"link"`
	Mime    string                 `json:"mime"`
	Name    string                 `json:"name"`
	Hash    string                 `json:"hash"`
	Size    int64                  `json:"size"`
	Width   int                    `json:"width"`
	Height  int                    `json:"height"`
	OCRText string                 `json:"ocrtext"`
	Thumbs  map[string]interface{} `json:"thumbs"`
	UserID  string                 `json:"user_id"`
}

type OcrResponse struct {
	Hash    string `json:"hash"`
	OCRText string `json:"ocrtext"`
}

type UserError struct {
	UserFacingMessage error
	LogMessage        error
}

func NewServer(c *config.Configuration, strategy imageprocessor.ImageProcessorStrategy, stats RuntimeStats) *Server {
	factory := imagestore.NewFactory(c)
	httpclient := &http.Client{}
	stores := factory.NewImageStores()

	hashGenerator := factory.NewHashGenerator(stores)
	authenticator := &PassthroughAuthenticator{}
	return &Server{c, httpclient, stores, hashGenerator, strategy, authenticator, stats}
}

func NewAuthenticatedServer(c *config.Configuration, strategy imageprocessor.ImageProcessorStrategy, auth Authenticator, stats RuntimeStats) *Server {
	factory := imagestore.NewFactory(c)
	httpclient := &http.Client{}
	stores := factory.NewImageStores()

	hashGenerator := factory.NewHashGenerator(stores)
	return &Server{c, httpclient, stores, hashGenerator, strategy, auth, stats}
}

func (s *Server) uploadFile(uploadFile io.Reader, fileName string, thumbs []*uploadedfile.ThumbFile, user *AuthenticatedUser) ServerResponse {
	tmpFile, err := saveToTmp(uploadFile)
	if err != nil {
		return ServerResponse{
			Error:  "Error saving to disk!",
			Status: http.StatusInternalServerError,
		}
	}

	upload, err := uploadedfile.NewUploadedFile(fileName, tmpFile, thumbs)
	defer upload.Clean()

	if err != nil {
		return ServerResponse{
			Error:  "Error detecting mime type!",
			Status: http.StatusInternalServerError,
		}
	}

	processor, err := s.processorStrategy(s.Config, upload)
	if err != nil {
		log.Printf("Error creating processor factory: %s", err.Error())
		return ServerResponse{
			Error:  "Unable to process image!",
			Status: http.StatusInternalServerError,
		}
	}

	err = processor.Run(upload)
	if err != nil {
		log.Printf("Error processing %+v: %s", upload, err.Error())
		return ServerResponse{
			Error:  "Unable to process image!",
			Status: http.StatusInternalServerError,
		}
	}

	upload.SetHash(s.hashGenerator.Get())

	factory := imagestore.NewFactory(s.Config)
	obj := factory.NewStoreObject(upload.GetHash(), upload.GetMime(), "original")

	uploadFilepath := upload.GetPath()
	obj, err = s.ImageStore.Save(uploadFilepath, obj)
	if err != nil {
		log.Printf("Error saving processed output to store: %s", err.Error())
		return ServerResponse{
			Error:  "Unable to save image!",
			Status: http.StatusInternalServerError,
		}
	}

	thumbsResp, err := s.buildThumbResponse(upload)
	if err != nil {
		log.Printf("Error processing %+v: %s", upload, err.Error())
		return ServerResponse{
			Error:  "Unable to process thumbnail!",
			Status: http.StatusInternalServerError,
		}
	}

	size, err := upload.FileSize()
	if err != nil {
		return ServerResponse{
			Error:  "Unable to fetch image metadata!",
			Status: http.StatusInternalServerError,
		}
	}

	width, height, err := upload.Dimensions()

	if err != nil {
		return ServerResponse{
			Error:  "Error fetching upload dimensions: " + err.Error(),
			Status: http.StatusInternalServerError,
		}
	}

	var userID string
	if user != nil {
		userID = string(user.UserID)
	}

	resp := ImageResponse{
		Link:    obj.Url,
		Mime:    obj.MimeType,
		Hash:    upload.GetHash(),
		Name:    fileName,
		Size:    size,
		Width:   width,
		Height:  height,
		OCRText: upload.GetOCRText(),
		Thumbs:  thumbsResp,
		UserID:  userID,
	}

	return ServerResponse{
		Data:   resp,
		Status: http.StatusOK,
	}
}

type fileExtractor func(r *http.Request) (uploadFile io.Reader, filename string, uerr *UserError)

func (s *Server) Configure(muxer *http.ServeMux) {

	var extractorFile fileExtractor = func(r *http.Request) (uploadFile io.Reader, filename string, uerr *UserError) {
		uploadFile, header, err := r.FormFile("image")
		if err != nil {
			return nil, "", &UserError{LogMessage: err, UserFacingMessage: errors.New("Error processing file")}
		}

		s.stats.Upload("file")
		return uploadFile, header.Filename, nil
	}

	var extractorUrl fileExtractor = func(r *http.Request) (uploadFile io.Reader, filename string, uerr *UserError) {
		url := r.FormValue("image")
		uploadFile, err := s.download(url)

		if err != nil {
			return nil, "", &UserError{LogMessage: err, UserFacingMessage: errors.New("Error downloading URL!")}
		}

		s.stats.Upload("url")
		return uploadFile, path.Base(url), nil
	}

	var extractorBase64 fileExtractor = func(r *http.Request) (uploadFile io.Reader, filename string, uerr *UserError) {
		input := r.FormValue("image")
		b64data := input[strings.IndexByte(input, ',')+1:]

		uploadFile = base64.NewDecoder(base64.StdEncoding, strings.NewReader(b64data))

		s.stats.Upload("base64")
		return uploadFile, "", nil
	}

	type uploadEndpoint func(fileExtractor, *AuthenticatedUser) http.HandlerFunc

	var uploadHandler uploadEndpoint = func(extractor fileExtractor, user *AuthenticatedUser) http.HandlerFunc {
		return func(w http.ResponseWriter, r *http.Request) {
			uploadFile, filename, uerr := extractor(r)
			if uerr != nil {
				log.Printf("Error extracting files: %s", uerr.LogMessage.Error())
				resp := ServerResponse{
					Status: http.StatusBadRequest,
					Error:  uerr.UserFacingMessage.Error(),
				}
				resp.Write(w, s.stats)
				return
			}

			thumbs, err := parseThumbs(r)
			if err != nil {
				resp := ServerResponse{
					Status: http.StatusBadRequest,
					Error:  "Error parsing thumbnails!",
				}
				resp.Write(w, s.stats)
				return
			}

			resp := s.uploadFile(uploadFile, filename, thumbs, user)

			switch uploadFile.(type) {
			case io.ReadCloser:
				defer uploadFile.(io.ReadCloser).Close()
				break
			default:
				break
			}

			resp.Write(w, s.stats)
		}
	}

	// Wrap an existing upload endpoint with authentication, returning a new endpoint that 4xxs unless authentication is passed.
	authenticatedEndpoint := func(endpoint uploadEndpoint, extractor fileExtractor) http.HandlerFunc {
		return func(w http.ResponseWriter, r *http.Request) {
			requestVars := mux.Vars(r)
			attemptedUserIdString, ok := requestVars["user_id"]

			// They didn't send a user ID to a /user endpoint
			if !ok || attemptedUserIdString == "" {
				w.WriteHeader(http.StatusBadRequest)
				return
			}

			user, err := s.authenticator.GetUser(r)

			// Their HMAC was invalid or they are trying to upload to someone else's account
			if user == nil || err != nil || user.UserID != attemptedUserIdString {
				w.WriteHeader(http.StatusUnauthorized)
				log.Printf("Authentication error: %s", err.Error())
				return
			}

			handler := endpoint(extractor, user)
			handler(w, r)
		}
	}

	ocrHandler := func(w http.ResponseWriter, r *http.Request) {
		imageID := r.FormValue("uid")
		if imageID == "" {
			resp := ServerResponse{
				Status: http.StatusBadRequest,
				Error:  "Image ID must be passed as \"uid\"",
			}
			resp.Write(w, s.stats)
			return
		}

		factory := imagestore.NewFactory(s.Config)
		tObj := factory.NewStoreObject(imageID, "", "original")

		storeReader, err := s.ImageStore.Get(tObj)
		if err != nil {
			resp := ServerResponse{
				Status: http.StatusBadRequest,
				Error:  fmt.Sprintf("Error retrieving image with ID: %s", imageID),
			}
			resp.Write(w, s.stats)
			return
		}
		defer storeReader.Close()

		storeFile, err := saveToTmp(storeReader)
		if err != nil {
			resp := ServerResponse{
				Status: http.StatusBadRequest,
				Error:  fmt.Sprintf("Error saving original image to tmpfile: %s", imageID),
			}
			resp.Write(w, s.stats)
			return
		}
		defer os.Remove(storeFile)

		upload, err := uploadedfile.NewUploadedFile("", storeFile, nil)
		if err != nil {
			resp := ServerResponse{
				Error:  fmt.Sprintf("Unable to generate UploadedFile object: %s", imageID),
				Status: http.StatusInternalServerError,
			}
			resp.Write(w, s.stats)
			return
		}
		upload.SetHash(imageID)
		defer upload.Clean()

		//TODO: fix this sp error:
		processor := imageprocessor.DuelOCRStratagy()
		err = processor.Process(upload)
		if err != nil {
			log.Printf("Error runinng DuelOCRStrategy on %+v: %s", upload, err.Error())
			resp := ServerResponse{
				Error:  "Unable to execute OCR strategy",
				Status: http.StatusInternalServerError,
			}
			resp.Write(w, s.stats)
			return
		}

		ocrResp := OcrResponse{
			Hash:    upload.GetHash(),
			OCRText: upload.GetOCRText(),
		}

		resp := ServerResponse{
			Data:   ocrResp,
			Status: http.StatusOK,
		}

		resp.Write(w, s.stats)
	}

	thumbnailHandler := func(w http.ResponseWriter, r *http.Request) {
		imageID := r.FormValue("uid")

		factory := imagestore.NewFactory(s.Config)
		tObj := factory.NewStoreObject(imageID, "", "original")

		thumbs, err := parseThumbs(r)
		if err != nil {
			resp := ServerResponse{
				Status: http.StatusBadRequest,
				Error:  "Error parsing thumbnails!",
			}
			resp.Write(w, s.stats)
			return
		}

		if len(thumbs) != 1 {
			resp := ServerResponse{
				Status: http.StatusBadRequest,
				Error:  "Wrong number of thumbnails, expected 1",
			}
			resp.Write(w, s.stats)
			return
		}

		storeReader, err := s.ImageStore.Get(tObj)
		if err != nil {
			resp := ServerResponse{
				Status: http.StatusNotFound,
				Error:  fmt.Sprintf("Error retrieving image with ID: %s", imageID),
			}
			resp.Write(w, s.stats)
			return
		}
		defer storeReader.Close()

		storeFile, err := saveToTmp(storeReader)
		if err != nil {
			resp := ServerResponse{
				Status: http.StatusInternalServerError,
				Error:  "Error saving original Image!",
			}
			resp.Write(w, s.stats)
			return
		}
		defer os.Remove(storeFile)

		upload, err := uploadedfile.NewUploadedFile("", storeFile, thumbs)
		if err != nil {
			log.Printf("Error processing %+v: %s", storeFile, err.Error())
			resp := ServerResponse{
				Error:  "Unable to process thumbnail!",
				Status: http.StatusInternalServerError,
			}
			resp.Write(w, s.stats)
			return
		}
		upload.SetHash(imageID)
		defer upload.Clean()

		processor, _ := imageprocessor.ThumbnailStrategy(s.Config, upload)
		err = processor.Run(upload)
		if err != nil {
			log.Printf("Error processing %+v: %s", upload, err.Error())
			resp := ServerResponse{
				Error:  "Unable to process thumbnail!",
				Status: http.StatusInternalServerError,
			}
			resp.Write(w, s.stats)
			return
		}

		ts := upload.GetThumbs()
		t := ts[0]

		if !t.GetNoStore() {
			thumbName := fmt.Sprintf("%s/%s", upload.GetHash(), t.Name)
			tObj = factory.NewStoreObject(thumbName, upload.GetMime(), "thumbnail")
			err = tObj.Store(t, s.ImageStore)
			if err != nil {
				log.Printf("Error storing %+v: %s", t, err.Error())
				resp := ServerResponse{
					Error:  "Unable to store thumbnail!",
					Status: http.StatusInternalServerError,
				}
				resp.Write(w, s.stats)
				return
			}
		}

		s.stats.Thumbnail(t.Name)

		http.ServeFile(w, r, t.GetPath())
	}

	rootHandler := func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "<html><head><title>An open source image uploader by Imgur</title></head><body style=\"background-color: #2b2b2b; color: white\">")
		fmt.Fprint(w, "Congratulations! Your image upload server is up and running. Head over to the <a style=\"color: #85bf25 \" href=\"https://github.com/Imgur/mandible\">github</a> page for documentation")
		fmt.Fprint(w, "<br/><br/><br/><img src=\"http://i.imgur.com/YbfUjs5.png?2\" />")
		fmt.Fprint(w, "</body></html>")
	}

	requestMiddleware := func(handler http.HandlerFunc) http.HandlerFunc {
		return func(w http.ResponseWriter, r *http.Request) {
			s.stats.Request(r.URL.Path)

			if os.Getenv("MANDIBLE_DEBUG") == "true" {
				r.ParseForm()
				log.Printf("Request url: %s with get params: %v and Headers: %v", r.URL.Path, r.Form, r.Header)
			}

			start := time.Now()
			handler(w, r)
			elapsed := time.Since(start)

			s.stats.ResponseTime(elapsed, r.URL.Path)
		}
	}

	router := mux.NewRouter()

	router.HandleFunc("/file", requestMiddleware(uploadHandler(extractorFile, nil)))
	router.HandleFunc("/url", requestMiddleware(uploadHandler(extractorUrl, nil)))
	router.HandleFunc("/base64", requestMiddleware(uploadHandler(extractorBase64, nil)))

	router.HandleFunc("/user/{user_id}/file", requestMiddleware(authenticatedEndpoint(uploadHandler, extractorBase64)))
	router.HandleFunc("/user/{user_id}/url", requestMiddleware(authenticatedEndpoint(uploadHandler, extractorUrl)))
	router.HandleFunc("/user/{user_id}/base64", requestMiddleware(authenticatedEndpoint(uploadHandler, extractorBase64)))

	router.HandleFunc("/thumbnail", requestMiddleware(thumbnailHandler))

	router.HandleFunc("/ocr", requestMiddleware(ocrHandler))
	router.HandleFunc("/", requestMiddleware(rootHandler))

	muxer.Handle("/", router)
}

func (s *Server) buildThumbResponse(upload *uploadedfile.UploadedFile) (map[string]interface{}, error) {
	factory := imagestore.NewFactory(s.Config)
	thumbsResp := map[string]interface{}{}

	for _, t := range upload.GetThumbs() {
		thumbName := fmt.Sprintf("%s/%s", upload.GetHash(), t.Name)
		tObj := factory.NewStoreObject(thumbName, upload.GetMime(), "thumbnail")
		err := tObj.Store(t, s.ImageStore)
		if err != nil {
			return nil, err
		}

		s.stats.Thumbnail(t.Name)
		thumbsResp[t.Name] = tObj.Url
	}

	return thumbsResp, nil
}

func (s *Server) download(url string) (io.ReadCloser, error) {
	req, err := http.NewRequest("GET", url, nil)

	if err != nil {
		return nil, err
	}

	req.Header.Add("User-Agent", s.Config.UserAgent)

	resp, err := s.HTTPClient.Do(req)

	if err != nil {
		// "HTTP protocol error" - maybe the server sent an invalid response or timed out
		return nil, err
	}

	if 200 != resp.StatusCode {
		return nil, errors.New("Non-200 status code received")
	}

	contentLength := resp.ContentLength

	if contentLength == 0 {
		return nil, errors.New("Empty file received")
	}

	return resp.Body, nil
}

func parseThumbs(r *http.Request) ([]*uploadedfile.ThumbFile, error) {
	thumbString := r.FormValue("thumbs")
	if thumbString == "" {
		return []*uploadedfile.ThumbFile{}, nil
	}

	type ThumbRequest struct {
		Width         int    `json:"width"`
		MaxWidth      int    `json:"max_width"`
		Height        int    `json:"height"`
		MaxHeight     int    `json:"max_height"`
		Shape         string `json:"shape"`
		CropGravity   string `json:"crop_gravity"`
		CropHeight    int    `json:"crop_height"`
		CropWidth     int    `json:"crop_width"`
		Quality       int    `json:"quality"`
		CropRatio     string `json:"crop_ratio"`
		DesiredFormat string `json:"format"`
		NoStore       bool   `json:"nostore"`
	}
	var thumbRequests map[string]ThumbRequest
	err := json.Unmarshal([]byte(thumbString), &thumbRequests)
	if err != nil {
		fmt.Println(err.Error())
		return nil, errors.New("Error parsing thumbnail JSON!")
	}

	var thumbs []*uploadedfile.ThumbFile
	for name, thumbRequest := range thumbRequests {
		thumb := uploadedfile.NewThumbFile(
			thumbRequest.Width,
			thumbRequest.MaxWidth,
			thumbRequest.Height,
			thumbRequest.MaxHeight,
			name,
			thumbRequest.Shape,
			"", // shape
			thumbRequest.CropGravity,
			thumbRequest.CropWidth,
			thumbRequest.CropHeight,
			thumbRequest.CropRatio,
			thumbRequest.Quality,
			thumbRequest.DesiredFormat,
			thumbRequest.NoStore,
		)

		thumbs = append(thumbs, thumb)
	}

	return thumbs, nil
}

func saveToTmp(upload io.Reader) (string, error) {
	tmpFile, err := ioutil.TempFile(os.TempDir(), "image")
	if err != nil {
		fmt.Println(err)

		return "", err
	}

	defer tmpFile.Close()

	_, err = io.Copy(tmpFile, upload)
	if err != nil {
		fmt.Println(err)

		return "", err
	}

	return tmpFile.Name(), nil
}


================================================
FILE: server/server_test.go
================================================
package server

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"testing"
	"time"

	"github.com/Imgur/mandible/config"
	"github.com/Imgur/mandible/imageprocessor"
	"github.com/Imgur/mandible/imagestore"
)

func TestRequestingTheFrontPageGetsSomeHTML(t *testing.T) {
	cfg := &config.Configuration{
		MaxFileSize: 99999999999,
		HashLength:  7,
		UserAgent:   "Foobar",
		Stores:      make([]map[string]string, 0),
		Port:        8888,
	}

	memcfg := make(map[string]string)
	memcfg["Type"] = "memory"
	cfg.Stores = append(cfg.Stores, memcfg)
	stats := &DiscardStats{}
	server := NewServer(cfg, imageprocessor.PassthroughStrategy, stats)

	muxer := http.NewServeMux()

	server.Configure(muxer)

	ts := httptest.NewServer(muxer)
	defer ts.Close()

	res, err := http.Get(ts.URL)
	if err != nil {
		t.Fatalf("Error when retrieving %s: %s", ts.URL, err.Error())
	}
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		t.Fatalf("Failed to read response body of %s: %s", ts.URL, err.Error())
	}

	t.Logf("Response to %s/ was: %s", ts.URL, body)

	if res.StatusCode != 200 {
		t.Fatalf("Unexpected status code %d", res.StatusCode)
	}

	sbody := string(body)

	if !strings.Contains(sbody, "<html>") {
		t.Fatalf("Did I get HTML back? Didn't find <html>...")
	}
}

func TestPostingBase64FilePutsTheFileInStorageAndReturnsJSON(t *testing.T) {
	cfg := &config.Configuration{
		MaxFileSize: 99999999999,
		HashLength:  7,
		UserAgent:   "Foobar",
		Stores:      make([]map[string]string, 0),
		Port:        8888,
	}

	memcfg := make(map[string]string)
	memcfg["Type"] = "memory"
	cfg.Stores = append(cfg.Stores, memcfg)
	stats := &DiscardStats{}
	server := NewServer(cfg, imageprocessor.PassthroughStrategy, stats)

	muxer := http.NewServeMux()

	server.Configure(muxer)

	ts := httptest.NewServer(muxer)
	defer ts.Close()

	// a 1x1 base64 encoded transparent GIF
	b64bytes, _ := base64.StdEncoding.DecodeString(b64gif)

	values := make(url.Values)
	values.Add("image", b64gif)

	res, err := http.PostForm(ts.URL+"/base64", values)
	if err != nil {
		t.Fatalf("Error when uploading base64 GIF: %s", err.Error())
	}
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		t.Fatalf("Failed to read response body: %s", err.Error())
	}

	t.Logf("Response to /base64 was: %s", body)

	if res.StatusCode != 200 {
		t.Fatalf("Unexpected status code %d", res.StatusCode)
	}

	var serverResp ServerResponse
	var imageResp ImageResponse
	err = json.Unmarshal(body, &serverResp)
	if err != nil {
		t.Fatalf("Unexpected error parsing response: %s", err.Error())
	}

	if !*serverResp.Success {
		t.Fatalf("Uploading GIF was unsuccessful")
	}

	imageRespBytes, _ := json.Marshal(serverResp.Data)

	err = json.Unmarshal(imageRespBytes, &imageResp)

	if imageResp.Height != 1 {
		t.Fatalf("Expected height to be 1, instead %d", imageResp.Height)
	}

	if imageResp.Width != 1 {
		t.Fatalf("Expected width to be 1, instead %d", imageResp.Width)
	}

	if imageResp.Size != 42 {
		t.Fatalf("Expected size to be 42, instead %d", imageResp.Size)
	}

	if imageResp.Mime != "image/gif" {
		t.Fatalf("Expected image MIME type to be image/gif, instead %s", imageResp.Mime)
	}

	immStore := server.ImageStore
	exists, err := immStore.Exists(&imagestore.StoreObject{Id: imageResp.Hash})
	if err != nil {
		t.Fatalf("Unexpected error checking if %s exists in in-memory image store: %s", imageResp.Hash, err.Error())
	}

	if !exists {
		t.Fatalf("Expected to find %s in the in-memory storage, instead absent. Dump: %+v", imageResp.Hash, immStore)
	}

	storedBodyReader, err := immStore.Get(&imagestore.StoreObject{Id: imageResp.Hash})
	if err != nil {
		t.Fatalf("Unexpected error fetching %s from in-memory image store: %s", imageResp.Hash, err.Error())
	}
	storedBodyBytes, _ := ioutil.ReadAll(storedBodyReader)

	if !bytes.Equal(storedBodyBytes, []byte(b64bytes)) {
		t.Fatalf("Stored bytes %s != %s", storedBodyBytes, []byte(b64bytes))
	}
}

func TestAuthentication(t *testing.T) {
	cfg := &config.Configuration{
		MaxFileSize: 99999999999,
		HashLength:  7,
		UserAgent:   "Foobar",
		Stores:      make([]map[string]string, 0),
		Port:        8888,
	}

	memcfg := make(map[string]string)
	memcfg["Type"] = "memory"
	cfg.Stores = append(cfg.Stores, memcfg)
	authenticator := NewHMACAuthenticatorSHA256([]byte("foobar"))
	stats := &DiscardStats{}
	server := NewAuthenticatedServer(cfg, imageprocessor.PassthroughStrategy, authenticator, stats)

	muxer := http.NewServeMux()

	server.Configure(muxer)

	ts := httptest.NewServer(muxer)
	defer ts.Close()

	values := make(url.Values)
	values.Add("image", b64gif)

	req, err := http.NewRequest("POST", ts.URL+"/user/123/base64", strings.NewReader(values.Encode()))
	if err != nil {
		t.Fatalf("Error when forming authenticated base64 GIF upload request: %s", err.Error())
	}

	message := AuthenticatedUser{
		UserID:               "123",
		GrantTime:            time.Now(),
		GrantDurationSeconds: 365 * 24 * 3600,
	}
	messageBytes, _ := json.Marshal(&message)
	messageMacWriter := hmac.New(sha256.New, []byte("foobar"))
	messageMacWriter.Write(messageBytes)
	messageMac := base64.StdEncoding.EncodeToString(messageMacWriter.Sum(nil))

	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Set("Authorization", string(messageBytes))
	req.Header.Set("X-Authorization-HMAC", string(messageMac))

	httpclient := http.Client{}
	res, err := httpclient.Do(req)
	if err != nil {
		t.Fatalf("Error when uploading authenticated base64 GIF: %s", err.Error())
	}
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		t.Fatalf("Failed to read response body: %s", err.Error())
	}

	t.Logf("Response to /base64 was: %s", body)

	if res.StatusCode != 200 {
		t.Fatalf("Unexpected status code %d", res.StatusCode)
	}

	var serverResp ServerResponse
	var imageResp ImageResponse
	err = json.Unmarshal(body, &serverResp)
	if err != nil {
		t.Fatalf("Unexpected error parsing response: %s", err.Error())
	}

	if !*serverResp.Success {
		t.Fatalf("Uploading GIF was unsuccessful")
	}

	imageRespBytes, _ := json.Marshal(serverResp.Data)

	err = json.Unmarshal(imageRespBytes, &imageResp)

	if imageResp.Mime != "image/gif" {
		t.Fatalf("Expected image MIME type to be image/gif, instead %s", imageResp.Mime)
	}

	if imageResp.UserID != "123" {
		t.Fatalf("Expected user ID to be \"123\", instead \"%s\"", imageResp.UserID)
	}
}

func TestGetFullWebpThumb(t *testing.T) {
	cfg := &config.Configuration{
		MaxFileSize: 99999999999,
		HashLength:  7,
		UserAgent:   "Foobar",
		Stores:      make([]map[string]string, 0),
		Port:        8888,
	}

	memcfg := make(map[string]string)
	memcfg["Type"] = "memory"
	cfg.Stores = append(cfg.Stores, memcfg)
	stats := &DiscardStats{}
	server := NewServer(cfg, imageprocessor.ThumbnailStrategy, stats)
	muxer := http.NewServeMux()
	server.Configure(muxer)
	ts := httptest.NewServer(muxer)
	defer ts.Close()

	thumbsJson, _ := json.Marshal(map[string]interface{}{
		"webp": map[string]interface{}{
			"format": "webp",
		},
	})

	values := make(url.Values)
	values.Add("image", b64dan)
	values.Add("thumbs", string(thumbsJson))

	res, err := http.PostForm(ts.URL+"/base64", values)
	if err != nil {
		t.Fatalf("Error when uploading base64 image: %s", err.Error())
	}
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		t.Fatalf("Failed to read response body: %s", err.Error())
	}

	t.Logf("Response to /base64 was: %s", body)

	if res.StatusCode != 200 {
		t.Fatalf("Unexpected status code %d", res.StatusCode)
	}

	var serverResp ServerResponse
	var imageResp ImageResponse
	err = json.Unmarshal(body, &serverResp)
	if err != nil {
		t.Fatalf("Unexpected error parsing response: %s", err.Error())
	}

	if !*serverResp.Success {
		t.Fatalf("Uploading image was unsuccessful")
	}

	imageRespBytes, _ := json.Marshal(serverResp.Data)

	err = json.Unmarshal(imageRespBytes, &imageResp)

	if len(imageResp.Thumbs) == 0 {
		t.Fatalf("Expected thumbs to contain data, instead blank")
	}

	if _, ok := imageResp.Thumbs["webp"]; !ok {
		t.Fatalf("Expected webp thumb, not given")
	}

	immStore := server.ImageStore
	storeId := imageResp.Hash + "/webp"

	exists, err := immStore.Exists(&imagestore.StoreObject{Id: storeId})
	if err != nil {
		t.Fatalf("Unexpected error checking if %s exists in in-memory image store: %s", storeId, err.Error())
	}
	if !exists {
		t.Fatalf("Expected to find %s in the in-memory storage, instead absent. Dump: %+v", storeId, immStore)
	}

	storedBodyReader, err := immStore.Get(&imagestore.StoreObject{Id: storeId})
	if err != nil {
		t.Fatalf("Unexpected error fetching %s from in-memory image store: %s", storeId, err.Error())
	}
	storedBodyBytes, _ := ioutil.ReadAll(storedBodyReader)

	if len(storedBodyBytes) == 0 {
		t.Fatalf("Expected webp thumbnail to be larger than 0 bytes")
	}

	if int64(len(storedBodyBytes)) >= imageResp.Size {
		t.Fatalf("Expected thumbnail to be smaller than original image, %v vs %v", int64(len(storedBodyBytes)), imageResp.Size)
	}
}

func TestGetSizedWebpThumb(t *testing.T) {
	cfg := &config.Configuration{
		MaxFileSize: 99999999999,
		HashLength:  7,
		UserAgent:   "Foobar",
		Stores:      make([]map[string]string, 0),
		Port:        8888,
	}

	memcfg := make(map[string]string)
	memcfg["Type"] = "memory"
	cfg.Stores = append(cfg.Stores, memcfg)
	stats := &DiscardStats{}
	server := NewServer(cfg, imageprocessor.ThumbnailStrategy, stats)
	muxer := http.NewServeMux()
	server.Configure(muxer)
	ts := httptest.NewServer(muxer)
	defer ts.Close()

	thumbsJson, _ := json.Marshal(map[string]interface{}{
		"webp": map[string]interface{}{
			"format": "webp",
		},
		"webpthumb": map[string]interface{}{
			"format": "webp",
			"shape":  "custom",
			"width":  10,
			"height": 10,
		},
	})

	values := make(url.Values)
	values.Add("image", b64dan)
	values.Add("thumbs", string(thumbsJson))

	res, err := http.PostForm(ts.URL+"/base64", values)
	if err != nil {
		t.Fatalf("Error when uploading base64 iamge: %s", err.Error())
	}
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		t.Fatalf("Failed to read response body: %s", err.Error())
	}

	t.Logf("Response to /base64 was: %s", body)

	if res.StatusCode != 200 {
		t.Fatalf("Unexpected status code %d", res.StatusCode)
	}

	var serverResp ServerResponse
	var imageResp ImageResponse
	err = json.Unmarshal(body, &serverResp)
	if err != nil {
		t.Fatalf("Unexpected error parsing response: %s", err.Error())
	}

	if !*serverResp.Success {
		t.Fatalf("Uploading image was unsuccessful")
	}

	imageRespBytes, _ := json.Marshal(serverResp.Data)

	err = json.Unmarshal(imageRespBytes, &imageResp)

	if len(imageResp.Thumbs) == 0 {
		t.Fatalf("Expected thumbs to contain data, instead blank")
	}

	if _, ok := imageResp.Thumbs["webp"]; !ok {
		t.Fatalf("Expected webp thumb, not given")
	}

	immStore := server.ImageStore
	storeId := imageResp.Hash + "/webp"
	storeIdSmall := imageResp.Hash + "/webpthumb"

	exists, err := immStore.Exists(&imagestore.StoreObject{Id: storeIdSmall})
	if err != nil {
		t.Fatalf("Unexpected error checking if %s exists in in-memory image store: %s", storeIdSmall, err.Error())
	}
	if !exists {
		t.Fatalf("Expected to find %s in the in-memory storage, instead absent. Dump: %+v", storeIdSmall, immStore)
	}

	storedBodyReader, err := immStore.Get(&imagestore.StoreObject{Id: storeId})
	if err != nil {
		t.Fatalf("Unexpected error fetching %s from in-memory image store: %s", storeId, err.Error())
	}
	storedBodyReaderSmall, err := immStore.Get(&imagestore.StoreObject{Id: storeIdSmall})
	if err != nil {
		t.Fatalf("Unexpected error fetching %s from in-memory image store: %s", storeIdSmall, err.Error())
	}
	storedBodyBytes, _ := ioutil.ReadAll(storedBodyReader)
	storedBodyBytesSmall, _ := ioutil.ReadAll(storedBodyReaderSmall)

	if len(storedBodyBytesSmall) == 0 {
		t.Fatalf("Expected webp thumbnail to be larger than 0 bytes")
	}

	if len(storedBodyBytesSmall) >= len(storedBodyBytes) {
		t.Fatalf("Expected thumbnail to be smaller than original image, %v vs %v", len(storedBodyBytesSmall), len(storedBodyBytes))
	}
}

func TestTooLarge(t *testing.T) {
	cfg := &config.Configuration{
		MaxFileSize: 99999999999,
		HashLength:  7,
		UserAgent:   "Foobar",
		Stores:      make([]map[string]string, 0),
		Port:        8888,
	}

	memcfg := make(map[string]string)
	memcfg["Type"] = "memory"
	cfg.Stores = append(cfg.Stores, memcfg)
	stats := &DiscardStats{}
	server := NewServer(cfg, imageprocessor.ThumbnailStrategy, stats)
	muxer := http.NewServeMux()
	server.Configure(muxer)
	ts := httptest.NewServer(muxer)
	defer ts.Close()

	thumbsJson, _ := json.Marshal(map[string]interface{}{
		"webp": map[string]interface{}{
			"format": "webp",
			"shape":  "custom",
			"width":  20000,
			"height": 20000,
		},
	})

	values := make(url.Values)
	values.Add("image", b64dan)
	values.Add("thumbs", string(thumbsJson))

	res, err := http.PostForm(ts.URL+"/base64", values)
	if err != nil {
		t.Fatalf("Error when uploading base64 iamge: %s", err.Error())
	}
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		t.Fatalf("Failed to read response body: %s", err.Error())
	}

	t.Logf("Response to /base64 was: %s", body)

	if res.StatusCode != 500 {
		t.Fatalf("Unexpected status code %d", res.StatusCode)
	}

	var serverResp ServerResponse
	err = json.Unmarshal(body, &serverResp)
	if err != nil {
		t.Fatalf("Unexpected error parsing response: %s", err.Error())
	}

	if *serverResp.Success {
		t.Fatalf("Uploading large image was successful")
	}
}

func TestTooSmall(t *testing.T) {
	cfg := &config.Configuration{
		MaxFileSize: 99999999999,
		HashLength:  7,
		UserAgent:   "Foobar",
		Stores:      make([]map[string]string, 0),
		Port:        8888,
	}

	memcfg := make(map[string]string)
	memcfg["Type"] = "memory"
	cfg.Stores = append(cfg.Stores, memcfg)
	stats := &DiscardStats{}
	server := NewServer(cfg, imageprocessor.ThumbnailStrategy, stats)
	muxer := http.NewServeMux()
	server.Configure(muxer)
	ts := httptest.NewServer(muxer)
	defer ts.Close()

	thumbsJson, _ := json.Marshal(map[string]interface{}{
		"webp": map[string]interface{}{
			"format": "webp",
			"shape":  "custom",
			"width":  0,
			"height": 0,
		},
	})

	values := make(url.Values)
	values.Add("image", b64dan)
	values.Add("thumbs", string(thumbsJson))

	res, err := http.PostForm(ts.URL+"/base64", values)
	if err != nil {
		t.Fatalf("Error when uploading base64 image: %s", err.Error())
	}
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		t.Fatalf("Failed to read response body: %s", err.Error())
	}

	t.Logf("Response to /base64 was: %s", body)

	if res.StatusCode != 500 {
		t.Fatalf("Unexpected status code %d", res.StatusCode)
	}

	var serverResp ServerResponse
	err = json.Unmarshal(body, &serverResp)
	if err != nil {
		t.Fatalf("Unexpected error parsing response: %s", err.Error())
	}

	if *serverResp.Success {
		t.Fatalf("Uploading small image was successful")
	}
}

func TestGetTallThumb(t *testing.T) {
	cfg := &config.Configuration{
		MaxFileSize: 99999999999,
		HashLength:  7,
		UserAgent:   "Foobar",
		Stores:      make([]map[string]string, 0),
		Port:        8888,
	}

	memcfg := make(map[string]string)
	memcfg["Type"] = "memory"
	cfg.Stores = append(cfg.Stores, memcfg)
	stats := &DiscardStats{}
	server := NewServer(cfg, imageprocessor.ThumbnailStrategy, stats)
	muxer := http.NewServeMux()
	server.Configure(muxer)
	ts := httptest.NewServer(muxer)
	defer ts.Close()

	thumbsJson, _ := json.Marshal(map[string]interface{}{
		"tallthumb": map[string]interface{}{
			"shape":        "custom",
			"crop_gravity": "north",
			"crop_ratio":   "1:2.25",
			"max_width":    10,
		},
	})

	values := make(url.Values)
	values.Add("image", b64dan)
	values.Add("thumbs", string(thumbsJson))

	res, err := http.PostForm(ts.URL+"/base64", values)
	if err != nil {
		t.Fatalf("Error when uploading base64 iamge: %s", err.Error())
	}
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		t.Fatalf("Failed to read response body: %s", err.Error())
	}

	t.Logf("Response to /base64 was: %s", body)

	if res.StatusCode != 200 {
		t.Fatalf("Unexpected status code %d", res.StatusCode)
	}

	var serverResp ServerResponse
	var imageResp ImageResponse
	err = json.Unmarshal(body, &serverResp)
	if err != nil {
		t.Fatalf("Unexpected error parsing response: %s", err.Error())
	}

	if !*serverResp.Success {
		t.Fatalf("Uploading image was unsuccessful")
	}

	imageRespBytes, _ := json.Marshal(serverResp.Data)

	err = json.Unmarshal(imageRespBytes, &imageResp)

	if len(imageResp.Thumbs) == 0 {
		t.Fatalf("Expected thumbs to contain data, instead blank")
	}

	if _, ok := imageResp.Thumbs["tallthumb"]; !ok {
		t.Fatalf("Expected cropped thumb, not given")
	}

	immStore := server.ImageStore
	storeId := imageResp.Hash
	storeIdSmall := imageResp.Hash + "/tallthumb"

	exists, err := immStore.Exists(&imagestore.StoreObject{Id: storeIdSmall})
	if err != nil {
		t.Fatalf("Unexpected error checking if %s exists in in-memory image store: %s", storeIdSmall, err.Error())
	}
	if !exists {
		t.Fatalf("Expected to find %s in the in-memory storage, instead absent. Dump: %+v", storeIdSmall, immStore)
	}

	storedBodyReader, err := immStore.Get(&imagestore.StoreObject{Id: storeId})
	if err != nil {
		t.Fatalf("Unexpected error fetching %s from in-memory image store: %s", storeId, err.Error())
	}
	storedBodyReaderSmall, err := immStore.Get(&imagestore.StoreObject{Id: storeIdSmall})
	if err != nil {
		t.Fatalf("Unexpected error fetching %s from in-memory image store: %s", storeIdSmall, err.Error())
	}
	storedBodyBytes, _ := ioutil.ReadAll(storedBodyReader)
	storedBodyBytesSmall, _ := ioutil.ReadAll(storedBodyReaderSmall)

	if len(storedBodyBytesSmall) == 0 {
		t.Fatalf("Expected webp thumbnail to be larger than 0 bytes")
	}

	if len(storedBodyBytesSmall) >= len(storedBodyBytes) {
		t.Fatalf("Expected thumbnail to be smaller than original image, %v vs %v", len(storedBodyBytesSmall), len(storedBodyBytes))
	}
}

var (
	b64gif = "R0lGODlhAQABAIAAAAAAAP" + "/" + "/" + "/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
	b64dan = "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAWAUlEQVRYw7V5eZBdV3nnd87dl/fu23tfXneru9Wtllp7y8Y2MpJtIMYTiBkYMFAZCFtqKiQMJjOkUsNUYJIKqRomhRNCGDAwsROQDHiRN2HtUktqSd3qVu/L63799v3d/d5z5g9M4mQIIn/Mr84ft26duvWr7/6+3/d956ADCbXumI6HHAwxzPgezjkucAAuSBgrLHIJbfhIlmTHtVxZ5m2L1vVEQnN1iwNbFGG9BG1BzrM9cGmZsm97+D0PffCJncN9mXTlmW/+T7c6wyP+8U89OXbgYLWqZzcKQ2GobLyUWr2Smr1dmzdOrkJ/r7RH9nMlYhRB0mDwoMBu5I0CkC4Gt/lkDfx9HeEhx8o16QUHAODxLjZS9TcNKji2KsN8wWyLQNdupdEw1SC0JyNr9fZQf2h3f9ys6cRzM47/xT/+w/GJAwAAAD2wdOr7G7Fd9/zWRz7y8zdwD9y+NvXs0yupSt2xpG4O1CCe2BOP+3nkGhtZulKC3FkPCQAMQBJAAagDjPHQF4JUHk4CWABDAKMAFACxQDzo1SB5fBfpHipnq7prarFIIBD1AvFgS7vTqNSzq+n0qsMnDk3cGwlzyWhcdZscD7NZ9Oh/+B0AeOW11774X5+8MTkFrMhFE67VCGh8F891dqgV30rNpVglxEVakd9EHbzcyZBNijlZe3skrCbEYCTou2wJy54UCoXY4bYWnuGoLAa1cHVz7vat01hCpbU1IYBFAeyMGeofNoPxeqMc0VTbIOupYjq9Fg2HRoYH3nH8Hb/5H5+8fGVq8vz5l09ffPHFF+FXIxgIaFpQo+jcqec4CRtYSqgBUWAdhuOAQwIVMQ7wgmW6hXrFcizXrqfXZ//+r34wf/H2vl2gRvHaGnGakOyBloGWConrdnmgs7Vvx0EDeOrwum5PvvoPRcx/8MOfeOmF888+/wr8W8BWrVw52/Sb1uX8FmWobdBKveJ7nqnbmWqD4aQWlW9VeFmprk5fmztfCwCEYyg2mIR4LLu5LcR1XlL29fTNr8nXbywin91/5OjSypZu1ro6drz8o0vb6392/3jfeK+6st5s/JqcWJb9vc/9yWah4NkucT1AKK5E69RByJFZrq67QVW6bywZijaLc9nMSv3h4+HMagUwyyC5a7CTC8vVdG7rVioYLFK3/vLVxrmpa3+a6A9Ijf/1F8+7oXiyNXQ1XZKFzYO7Yn0KXW6o06ncr8OMYao11vFkQjQACSDGCmGOa3i2iKGXwKG4lGypBGTXs3yGcXqGI1pbBAtSJN5HefnqhctzF1NLW87klU270HSBSRvuG9duW6u5etFbqDXzTZMCbFWs8b6OUI9/qC+6smHXbPtXc8IYM+0sGyBEABjBOIDQtGMqthHzfNd2w8Rrj1mBKAlH1Y07teK2nxyNhxN929laoVgqZtdIOe+UQAKQGcjVvYbjcQA1F3Ilmye0DEAAAEBgICDYbKh1ICZgYt3e1O9Ki816XgwgjhHBKOVTAUAAaAfYI2G2g5nMunjTTChbmRK0akg3vOzmAkeF7r62AM8FhsaU3wpIctBxvUyxsbGQqtQKOm7OXK+U6qACEAAXQKNQqdQHhdaiZQeDXkcikM7fRWZsLKTRaq1OYdXzEUAPQAeDNBnCIrOccZs+H6BQKLmqSrV2UNTWh4/e19bWHolpWjAKiAVVBlUEwwSLgmlvbiwuL90+r5wplO1s0ZxZKhUphGRoT3YDW7s+v8SaVJPVNNyFFvrvv/8H/+MvvsYCSABhgCEBNUW8YvmjAfAZJmuyySA5cF9PKBGPReOHJw51j+wBOQDIB5YDH0PTAUSBw0B4MDwwDDe3nc5texjrHj19/szZy1fEWBQLXDqzvr3myCxeb+Ca5f3qTGQ+9sQnGeKsLC/1A/SyKCzD2QbZ9uDe+ztKDXMh64wPsAce7Bkd2L97566OjnbgRfApeDYl1Pd85ANQjmIBYZG4PvI8RpRDoYgmy4FgYGjXrlhLtFYqbS4vrs05rIM8h6Ztcldt4R+/fn7i+LvG+rqbAADwsyYtEohFg70j/Rww4zK0tDEUeIFHImAgDLFdIEB9FvkMSxkAQAgwUJ/YwIPPeMQ1wPbBcp1q1a/ooz1jw8O7tIDWGcetEdrVGUGYubtB1E2fATR+YP/Jy5fuEKhSAICBHa0T/ZH1S6uEUE3zdu8Z2dk/Gg5HAFEQeRAVQCyiCAgABd/zgTIMiMhnkeMgy0KW6zu27/u1aq3eqKvxUL1p5CpbSlg5eGCwYaFMsX6XTGzt7jO4sNK5+9O/+0c3V2dyG2vLs7dc26ivlfIV4mGQAmyAESJyCHiGUh8BAkQopr7lYsogj0WOB8igPEtZFrM8YI74LkEMweBjQomjuHxPx8D06jaDLYE6CYnc3ei//tdPeTwLlh8Vgw7TzG9vPvOtb65Nff/69HwVoF+CiByIaZ3ACmA4LkJYRSzlkEsRAt8njONgDyNOIoQS8BFlwWWJ71LfIb5DiccyrOuavGAO7+lcnp2fvjabrvwa9eepr35ho5DhbSIyaslt+qwwkoh0ydyNO80GAEIwtvPQYHIMPB9cn5VkjDhKKEgClhTsM2AB8VkCPDYNxjURyxCFQxbn2k3XchiEAVOf4ZpG06OWEgnnUoV81bs7re8//fTPn/btPvy+J35zZOLYM1//+uqNCmtDfyT4zo/enxwZBs8AJQAiwhwDjoUoARcD9SHWC4FWDED9BhgqNXXADsIUOy7ne5zvc4RFxPZ9h5q0spFmFT6eDLP5Clh3YcYghGNAKUChWWcQRNq6NaM+1JiLuxbPK7/3t3/ZOfFuYCmmpJHOLy+s6RWTIWxuaev26+ezM7eM4pKMDY7nUSAASgBhhGwKCLOixFBkOMT2kNVwc8Xs1JWb2Y2iHMGZKlNtunepiQKDDEo5ANN1lheXJq9Mf2C87zOPPuz6mfmtVEB2enYOL3n84x/7428883pH745gYuDqzZWFjXy64ly9Pp1NrQ+0tahxBZwmNSiql0gh69sOViRWFBHDGq7XqJQKta0LF1ZqJdqawNcWTY/+qlARAqztEwD4x+JpV3OdIZl91/F+PdVRTw/GYvjSy0bOOHfxat/Yvg+959j01KTPu6HRZKaQQSWlYfPf+D8/vWd24eHPfgozHNQbhlVaW1xNl7KW54mSghhEVV/EIb2ByizcSUuWb91NWoT97Oe+pPKSTxESEctIgmP0D3WA0dxc26Ieam+Jy1gaC7m/f9/YkmH+5AffW5y68UalVI0mHjw0HrQLnGupQe3ET85+5+zSpz/0GG83N9cz+cz6rdVlD/k7h3clNA3zni1DgyXA8pZu8wDO/0NE5tnDY8n9XWxMtbs72llVE4DaEiOV641CIRv16uoD/ZAxSltmJJgI8xJIIXli5+fd0qnT17tHR0cP7e9YTb987dbRiXeUlBvlOzcfOjJuiotf/ObzJ55/1fHsw6Ndh3cPR3tHo4Egdt1SUV9ZmBYVyxFxT7v87B+9jzQbnIyuzpl/9t3J3h3tQcH/jaPjxw4llMEIMBY0V8EDBAAYQAAwAQCgFcHqc38jde0oVRt3rvxob3+f0jUIg+1Gc3P2J5c6kmMoIkhiq2kahfU0sYyx0eRT3/mbp3/66k9//Mrc6Rsf+MKTx963XwzHrAYNE7ZL5USB5Ot6qWzeXssFYjgZk3zbjEdV1xQuTW1/+9tf+7u//cbK6oLjmQ29qdvIMF2GBRYA4mrQsAzwPACIK5KkaSCZQkPv6UtShgDySd2SE4OD98vbc8t2gdioIIakYJBN7j9o68a5c1e+/Aefb9k/Ri7efPdI/8MPHs9W9af++sTQQGdhbWmwt3380EO+oK6ffO3UGxff+uN4gIOPfybWvtOhw65HeVHlFU6V5IAqswDgMmj/oSO3V1Yc29nVOwJCAIZ7zMKVejEb7e4E8LBDoWRobQktGKzenM+tbabXa1mwlu/c2sxkPv6pjx//d4/C2uxaPt10zI5Ix0hcaPtkhJfxjclXeAGvzC1mGm7Va4wd2LG+WtOrZUI8DqMgB8VS8dO/++jgyO5SvgCEEs8HzyHUZYMcX67VQuHQM8+enN/WtXoDqgR8UUbYwQQRDJZNbRsQCwQQFkN794YG9uzwGIdzyht39uwaTewZhfI2WIwqcpi6J5/9+wceOtaZTBBdf/s9j5ieszR/e/n6qrxD//JXDz75sdM3L3kA4BHKMQwD/lf/2xd+icuHMHYAXjj9ajafrTm0US6dDEr/6bF3huSmuCMKIADhiNFAHsKiSiUBBYMQEjBFottssSuM34D1BUpZ5EkVZD34zqNmoTlz9qIUUGReFJRg0dSNOg7JdmsyPbeUKxffNFIK4LOYgP9WH+U4FjM8L4hon6JYur78i6QVpICNpBYj/+UnDr3r/e+NYk3kBBA5pGhEkKmsMkoQmk0ztW4Uc2FZwAJQxkNaAkre6TM/K7jWIw+826zXbs3ebBiO5/g5vVi1nKWV21YyvVGEa6+96aT7x/fJUDvy4CNvf/f7zWZNZXmGUgZhiihBhI3ynOWxImA70j6b27Qd+7HH/n2Pmg/0EKteMFWecQjveZRhMYNBJ9BompmMYdVNu1reLPT2Jbkd/dC+A8SmzFzlmjbSQq0tLYrIluoNt2bnm4WN8srrb9SvTHKEYQAsAARAtjPbbSqbWl372cs/rVcrjmWahmmalmMbruewPMuSUBD52JNkFiHGd3584lsffehg575dlVI1KLW7iCLHQTWdIYyNDbNepz5Ed+3yfPu5P//qC8+f+PDn/0usZw9wTTPAeXUWAAPDUMwC4Lpj5xq6UfMV23aog3wW4M1oZXJZzo9PPfciwIu/rJ2nkNNtTRJtp8EDdAG3AG5bTBF5tlgzEgg88ASGCyqiA262USccam1JEMdgFem9v/2Jcy+8dOrET7SL19aW1y+8fu3Yex7hRR4wBpYjNp1fXCoh/ZNf+dLQg8dPfeCzlHq/0BUAAIu9Vk3J1vRfMmLsVaWZSq1umh4Q10MRIvtgPfmRhx1S3a42A1rMJS5hGTUY4hTZsu3FteWt9JamBTy9ks5vqx1dJcc7fea1wvbmYM/w0eMPd/Z02LWyrjeyuULJM8aPTnQO9/WOH1ad8sZqpqMlsjPZHlKkbLnOOSRnWL+0g0Af701c36hsU9cGMBEjU/quwzu+/7XPvXLmhcm5jaMPvFNTRODEeKK9pbPTNvQf/vhEZmWzXQtF4iEhGjYZQVKjlmcsLc3cN/a2gVgftpuOZ+X12ura+ts++qFAWC3Nzwf6h3h9izIYxdsBePCslZV8eX7x7PnL333u9Mzy+r+MVkJifFaNaEGPxUXLsoB+5XceHdw30ijU55YWDddQlCAlgDheVoJ1s9HZ0fnAvQ96q3kmaxpFo7qZpbpTadZdjrWw0tB14jc4TFMrGy3jw117j29dejE80C+EOt3SNNM+BBAFCACOR2KJjuGBex5626c/8V7Vdl69eOOf9VvbFtkwGim9WbVtAHjiyPh//sR7kdXEjHJncW4lteAQQAyrhLXtXCaf3e5p61S7Eh29nd2dgzvah2J8zMs3lq5c3rqzWKrWG77OqgjZDgjC3vd/1GimK9tbiZ1H3Nw6iMDI/ZWl2frKTcvKOnqeVwWEWeDIPRO7n3/xTCZX+qfJx6CUE/juSPjYvqHHDiR/4/j9EIuQQjHRoo3uHLn1o2kfZpouqXpOOBQhlp+PFoOtcd+upApb5YyZULt6BgYdzu1HjtARrXk1RQ7WK/W20UFAofLsq6GeAYAA6EWuqw1AWLsxOXX5tSMTD4wemADP8zzMmDqicHT/yPXpxbccJGH45p88+Z3vfuU9x0YG9yaBZYBBoKrUo6Fo9M7s1fnZUi6fohwfjsSIy2lKqLWrHTFsrlS5MnNjKrdSkJ1gT1vrQH9Xb3ssEiIeUy7WBsd3SyEuNTnZtnMYcwzZXmbaOozs9g/+/E8FzLfGu9xijkEmDcZYPgTlRqVa8DwS12KpbJYCMACQzxcef8eEsGMnNGsUiwQzIIrAcaqsdHX0TF+7klp3edV0/CamcjiktcdVJhSOtXZHRJVwAhsUtVDQMW3HbHiELK+mbl29MX7wkJpQVmbmu4eSeq30o6f+crAjKoZaL516OZXfdH2IKGLbkXEh1Is4GSHXdY1b567WGv5GMQ+EMCzLpjL57z370sTBA117HkGKDxWLADDRIPFoRI5E4m03rl5KbZoGykk8p2mBUiUXYCVZCtqOjxkuEg5zLItZdiuXX9lcn5yc+vaJM/GgenDP3q217UBIDLT3fOkzf7gwdfvY+96vBRI5veEa1eG+rpa9+4ALALDAgVmtn79w89b8FisIkUCAwRgTQhqm9e2n/4Ga+sTEvXx7D8Y+cQiOqmD7sXA83huau3F7btqvoRqhiBKlYjvlhrmRz20WNijD5HK1uZWbs6uzz710eT3V0Hlt5c7tT33wCZ7wSwtz3XsONzO5xampYxNHJCVqmH6zlu1pDSZ2DFApiEAE5CPDmLmzAASN9LfuHmx/k9bPhXbmwuUfPP1D5Dm7BncIbYPASkjlgKBEuK0/mUhtLF+eqS8v5zzL9HFjcXOjWK8rslgqlG/MzLx+9o3XLszNbzZ04LRgMJXe/Nxvf5BUGhdOvbr37Q8mRCGzMsPyvGV6iFcYzxob7pF6O5AQoiAjBAKQW9dvXbhwJSzrvlP6Z7QAoNponnrt3HeePpnf3EqIXGtvkon0SiwvMELnzphs5lcXSpObxVvTqzeXVuZX11fW1+fuTJ+5Mju9pusWAIBtm5VqyaFQS904e/LvGIru/cCHjdSm4dlSJCAqku84gtsc6u9EEY3KUYAwohS53vydhe/98PnsVnkjXflHWuitPts0zQuTU3/19A8nX59s5NMBVYy3dPa0Dyf7e6Ihm9XLhaxd0UmlbKW3aqvbes0kgMWAojmO+eYkoygWLQyNJjuTfZXZW2XbHTxyz8joztZgUK9sdUQCQS1MNA2pLQgkAIfqte18bnHxcrZhi7KEWJb1vLuN3hgf3jt634GJZLJHZJukuVxaX8wsZ5fmizeKJP3z2xeEMca+/+an9uzf87+/9bXzJ57tjgUZz9+5ZyIUaZUwlRXs17axUUcBBdp7INYPOAhWvZlLT96aOnvhnGm7iiCyv84puU/IxeszF6/PAEAsEu5oi8sigibK2GjrF3soJb7/T2JYvLOgqO3DYwdlu3zvkXvAg3pBB4GHkMhoMcBANRGAIs8CXgUPOSZwgixJmkvqDub+pbbuCsO0coXSVqa0VdKrzr86tHuud+naNcwxMUyTLWHMghgIMCKPFIHaBjCIRkLASUhQAfNgOrVaEQRhPbU9uzyPOIahlML/H2S20ucvXM2ks/eO9Ye0AIOA2Cb2bERMhAHkADAqsAryXNqoWnZTCAXqzeby4qLEi4woipRShmHwvw3MW9a/AoQIhfV8eX1zuzvZZeuG3TQdQ3dtCwPHMCJGLKKU2o5vmJwoEl40LW/hzrypm/8XZCy0eCnDy+0AAAAASUVORK5CYII="
)


================================================
FILE: server/stats.go
================================================
package server

import (
	"fmt"
	"net"
	"time"

	"github.com/PagerDuty/godspeed"
)

type RuntimeStats interface {
	LogStartup()

	Request(url string)
	ResponseTime(elapsed time.Duration, url string)
	Thumbnail(name string)
	Upload(source string)
	Error(code int)
}

type DiscardStats struct{}

func (d *DiscardStats) LogStartup()                                    {}
func (d *DiscardStats) Request(url string)                             {}
func (d *DiscardStats) ResponseTime(elapsed time.Duration, url string) {}
func (d *DiscardStats) Thumbnail(name string)                          {}
func (d *DiscardStats) Upload(source string)                           {}
func (d *DiscardStats) Error(code int)                                 {}

type DatadogStats struct {
	dog *godspeed.Godspeed
}

func NewDatadogStats(datadogHost string) (*DatadogStats, error) {
	var ip net.IP = nil
	var err error = nil

	// Assume datadogHost is an IP and try to parse it
	ip = net.ParseIP(datadogHost)

	// Parsing failed
	if ip == nil {
		ips, _ := net.LookupIP(datadogHost)

		if len(ips) > 0 {
			ip = ips[0]
		}
	}

	if ip != nil {
		gdsp, err := godspeed.New(ip.String(), godspeed.DefaultPort, false)
		if err == nil {
			return &DatadogStats{gdsp}, nil
		}
	}

	return nil, err
}

func (d *DatadogStats) LogStartup() {
	d.dog.Incr("mandible.startup", nil)
}

func (d *DatadogStats) Request(url string) {
	tag := fmt.Sprintf("url:%s", url)

	d.dog.Incr("mandible.request", []string{tag})
}

func (d *DatadogStats) ResponseTime(elapsed time.Duration, url string) {
	time := elapsed.Seconds()
	tag := fmt.Sprintf("url:%s", url)

	d.dog.Timing("mandible.responseTime", time, []string{tag})
}

func (d *DatadogStats) Thumbnail(name string) {
	tag := fmt.Sprintf("size:%s", name)

	d.dog.Incr("mandible.thumbnail", []string{tag})
}

func (d *DatadogStats) Upload(source string) {
	tag := fmt.Sprintf("source:%s", source)

	d.dog.Incr("mandible.upload", []string{tag})
}

func (d *DatadogStats) Error(code int) {
	tag := fmt.Sprintf("code:%d", code)
	d.dog.Incr("mandible.error", []string{tag})
}


================================================
FILE: uploadedfile/thumbfile.go
================================================
package uploadedfile

import (
	"errors"
	"fmt"
	"math"
	"os"
	"regexp"
	"strconv"

	"github.com/Imgur/mandible/imageprocessor/processorcommand"
	"github.com/Imgur/mandible/imageprocessor/thumbType"
)

var (
	defaultQuality   = 83
	maxImageSideSize = 10000
)

type ThumbFile struct {
	localPath string

	Name          string
	Width         int
	MaxWidth      int
	Height        int
	MaxHeight     int
	Shape         string
	CropGravity   string
	CropWidth     int
	CropHeight    int
	CropRatio     string
	Quality       int
	Format        string
	StoreURI      string
	DesiredFormat string
	NoStore       bool
}

func NewThumbFile(width, maxWidth, height, maxHeight int, name, shape, path, cropGravity string, cropWidth, cropHeight int, cropRatio string, quality int, desiredFormat string, noStore bool) *ThumbFile {
	if quality == 0 {
		quality = defaultQuality
	}

	return &ThumbFile{
		localPath: path,

		Name:          name,
		Width:         width,
		MaxWidth:      maxWidth,
		Height:        height,
		MaxHeight:     maxHeight,
		Shape:         shape,
		CropGravity:   cropGravity,
		CropWidth:     cropWidth,
		CropHeight:    cropHeight,
		CropRatio:     cropRatio,
		Quality:       quality,
		Format:        "",
		StoreURI:      "",
		DesiredFormat: desiredFormat,
		NoStore:       noStore,
	}
}

func (this *ThumbFile) GetNoStore() bool {
	return this.NoStore
}

func (this *ThumbFile) SetPath(path string) error {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return errors.New(fmt.Sprintf("Error when creating thumbnail %s", this.Name))
	}

	this.localPath = path

	return nil
}

func (this *ThumbFile) GetPath() string {
	return this.localPath
}

func (this *ThumbFile) GetOutputFormat(original *UploadedFile) thumbType.ThumbType {
	if this.DesiredFormat != "" {
		return thumbType.FromString(this.DesiredFormat)
	}

	return thumbType.FromMime(original.GetMime())
}

func (this *ThumbFile) ComputeWidth(original *UploadedFile) int {
	width := this.Width

	oWidth, _, err := original.Dimensions()
	if err != nil {
		return 0
	}

	if this.MaxWidth > 0 {
		width = int(math.Min(float64(oWidth), float64(this.MaxWidth)))
	}

	return width
}

func (this *ThumbFile) ComputeHeight(original *UploadedFile) int {
	height := this.Height

	_, oHeight, err := original.Dimensions()
	if err != nil {
		return 0
	}

	if this.MaxHeight > 0 {
		height = int(math.Min(float64(oHeight), float64(this.MaxHeight)))
	}

	return height
}

func (this *ThumbFile) ComputeCrop(original *UploadedFile) (int, int, error) {
	re := regexp.MustCompile("(.*):(.*)")
	matches := re.FindStringSubmatch(this.CropRatio)
	if len(matches) != 3 {
		return 0, 0, errors.New("Invalid crop_ratio")
	}

	wRatio, werr := strconv.ParseFloat(matches[1], 64)
	hRatio, herr := strconv.ParseFloat(matches[2], 64)
	if werr != nil || herr != nil {
		return 0, 0, errors.New("Invalid crop_ratio")
	}

	var cropWidth, cropHeight float64

	if wRatio >= hRatio {
		wRatio = wRatio / hRatio
		hRatio = 1
		cropWidth = math.Ceil(float64(this.ComputeHeight(original)) * wRatio)
		cropHeight = math.Ceil(float64(this.ComputeHeight(original)) * hRatio)
	} else {
		hRatio = hRatio / wRatio
		wRatio = 1
		cropWidth = math.Ceil(float64(this.ComputeWidth(original)) * wRatio)
		cropHeight = math.Ceil(float64(this.ComputeWidth(original)) * hRatio)
	}

	return int(cropWidth), int(cropHeight), nil
}

func (this *ThumbFile) Process(original *UploadedFile) error {
	switch this.Shape {
	case "circle":
		return this.processCircle(original)
	case "thumb":
		return this.processThumb(original)
	case "square":
		return this.processSquare(original)
	case "custom":
		return this.processCustom(original)
	default:
		return this.processFull(original)
	}
}

func (this *ThumbFile) String() string {
	return fmt.Sprintf("Thumbnail of <%s>", this.Name)
}

func (this *ThumbFile) processSquare(original *UploadedFile) error {
	if this.Width == 0 {
		return errors.New("Width cannot be 0")
	}
	if this.Width > maxImageSideSize {
		return errors.New("Width too large")
	}

	filename, err := processorcommand.SquareThumb(original.GetPath(), this.Name, this.Width, this.Quality, this.GetOutputFormat(original))
	if err != nil {
		return err
	}

	if err := this.SetPath(filename); err != nil {
		return err
	}

	return nil
}

func (this *ThumbFile) processCircle(original *UploadedFile) error {
	if this.Width == 0 {
		return errors.New("Width cannot be 0")
	}
	if this.Width > maxImageSideSize {
		return errors.New("Width too large")
	}

	//Circle thumbs should always be PNGs
	outputFormat := thumbType.FromString("png")

	filename, err := processorcommand.CircleThumb(original.GetPath(), this.Name, this.Width, this.Quality, outputFormat)
	if err != nil {
		return err
	}

	if err := this.SetPath(filename); err != nil {
		return err
	}

	return nil
}

func (this *ThumbFile) processThumb(original *UploadedFile) error {
	if this.Width == 0 {
		return errors.New("Width cannot be 0")
	}
	if this.Width > maxImageSideSize {
		return errors.New("Width too large")
	}
	if this.Height == 0 {
		return errors.New("Height cannot be 0")
	}
	if this.Height > maxImageSideSize {
		return errors.New("Height too large")
	}

	filename, err := processorcommand.Thumb(original.GetPath(), this.Name, this.Width, this.Height, this.Quality, this.GetOutputFormat(original))
	if err != nil {
		return err
	}

	if err := this.SetPath(filename); err != nil {
		return err
	}

	return nil
}

func (this *ThumbFile) processCustom(original *UploadedFile) error {
	cropWidth := this.CropWidth
	cropHeight := this.CropHeight
	var err error

	if this.CropRatio != "" {
		cropWidth, cropHeight, err = this.ComputeCrop(original)
		if err != nil {
			return err
		}
	}

	width := this.ComputeWidth(original)
	height := this.ComputeHeight(original)
	validWidth := width > 0 && width <= maxImageSideSize
	validHeight := height > 0 && height <= maxImageSideSize

	if !validWidth && !validHeight {
		if !validWidth {
			return errors.New("Invalid width")
		}

		return errors.New("Invalid height")
	}

	filename, err := processorcommand.CustomThumb(original.GetPath(), this.Name, width, height, this.CropGravity, cropWidth, cropHeight, this.Quality, this.GetOutputFormat(original))
	if err != nil {
		return err
	}

	if err := this.SetPath(filename); err != nil {
		return err
	}

	return nil
}

func (this *ThumbFile) processFull(original *UploadedFile) error {
	filename, err := processorcommand.Full(original.GetPath(), this.Name, this.Quality, this.GetOutputFormat(original))
	if err != nil {
		return err
	}

	if err := this.SetPath(filename); err != nil {
		return err
	}

	return nil
}


================================================
FILE: uploadedfile/uploadedfile.go
================================================
package uploadedfile

import (
	"errors"
	"image"
	"image/gif"
	"image/jpeg"
	"image/png"
	"net/http"
	"os"
)

type UploadedFile struct {
	filename string
	path     string
	mime     string
	hash     string
	ocrText  string
	thumbs   []*ThumbFile
}

var supportedTypes = map[string]bool{
	"image/jpeg": true,
	"image/jpg":  true,
	"image/gif":  true,
	"image/png":  true,
}

func NewUploadedFile(filename, path string, thumbs []*ThumbFile) (*UploadedFile, error) {
	file, err := os.Open(path)

	if err != nil {
		return nil, err
	}

	buff := make([]byte, 512) // http://golang.org/pkg/net/http/#DetectContentType
	_, err = file.Read(buff)

	if err != nil {
		return nil, err
	}

	filetype := http.DetectContentType(buff)

	if _, ok := supportedTypes[filetype]; !ok {
		return nil, errors.New("Unsupported file type!")
	}

	return &UploadedFile{
		filename,
		path,
		filetype,
		"",
		"",
		thumbs,
	}, nil
}

func (this *UploadedFile) GetFilename() string {
	return this.filename
}

func (this *UploadedFile) SetFilename(filename string) {
	this.filename = filename
}

func (this *UploadedFile) GetHash() string {
	return this.hash
}

func (this *UploadedFile) SetHash(hash string) {
	this.hash = hash
}

func (this *UploadedFile) GetOCRText() string {
	return this.ocrText
}

func (this *UploadedFile) SetOCRText(text string) {
	this.ocrText = text
}

func (this *UploadedFile) SetPath(path string) {
	// TODO: find a better location for this
	os.Remove(this.path)

	this.path = path
}

func (this *UploadedFile) GetPath() string {
	return this.path
}

func (this *UploadedFile) GetMime() string {
	return this.mime
}

func (this *UploadedFile) SetMime(mime string) {
	this.mime = mime
}

func (this *UploadedFile) SetThumbs(thumbs []*ThumbFile) {
	this.thumbs = thumbs
}

func (this *UploadedFile) GetThumbs() []*ThumbFile {
	return this.thumbs
}

func (this *UploadedFile) FileSize() (int64, error) {
	f, err := os.Open(this.path)
	if err != nil {
		return 0, err
	}

	stats, err := f.Stat()
	if err != nil {
		return 0, err
	}

	size := stats.Size()

	return size, nil
}

func (this *UploadedFile) Clean() {
	os.Remove(this.path)

	for _, thumb := range this.thumbs {
		os.Remove(thumb.GetPath())
	}
}

func (this *UploadedFile) Dimensions() (int, int, error) {
	f, err := os.Open(this.path)
	if err != nil {
		return 0, 0, err
	}

	var cfg image.Config
	switch true {
	case this.IsGif():
		cfg, err = gif.DecodeConfig(f)
	case this.IsPng():
		cfg, err = png.DecodeConfig(f)
	case this.IsJpeg():
		cfg, err = jpeg.DecodeConfig(f)
	default:
		return 0, 0, errors.New("Invalid mime type!")
	}

	if err != nil {
		return 0, 0, err
	}

	return cfg.Width, cfg.Height, nil
}

func (this *UploadedFile) IsJpeg() bool {
	return (this.GetMime() == "image/jpeg" || this.GetMime() == "image/jpg")
}

func (this *UploadedFile) IsPng() bool {
	return this.GetMime() == "image/png"
}

func (this *UploadedFile) IsGif() bool {
	return this.GetMime() == "image/gif"
}


================================================
FILE: vendor/github.com/PagerDuty/godspeed/.gitignore
================================================
# Misc
*.swp

# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so

# Folders
_obj
_test

# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out

*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*

_testmain.go

*.exe
*.test
*.prof


================================================
FILE: vendor/github.com/PagerDuty/godspeed/.travis.yml
================================================
language: go
go:
  - 1.5.3
branches:
  only:
    - master
script: go test -v ./... -check.vv
sudo: false


================================================
FILE: vendor/github.com/PagerDuty/godspeed/LICENSE
================================================
Copyright (c) 2014-2015, PagerDuty Inc.
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.

3. Neither the name of PagerDuty nor the names of its contributors may be used
   to endorse or promote products derived from this software without specific
   prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 PagerDuty 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.


================================================
FILE: vendor/github.com/PagerDuty/godspeed/README.md
================================================
# Godspeed
[![TravisCI Build Status](https://img.shields.io/travis/PagerDuty/godspeed/master.svg?style=flat)](https://travis-ci.org/PagerDuty/godspeed)
[![GoDoc](https://img.shields.io/badge/godspeed-GoDoc-blue.svg?style=flat)](https://godoc.org/github.com/PagerDuty/godspeed)
[![License](https://img.shields.io/badge/License-BSD_3--Clause-brightgreen.svg?style=flat)](https://github.com/PagerDuty/godspeed/blob/master/LICENSE)

Godspeed is a statsd client for the Datadog extension of statsd (DogStatsD).
The name `godspeed` is a bit of a rhyming slang twist on DogStatsD. It's also a
poke at the fact that the statsd protocol's transport mechanism is UDP...

Check out [GoDoc](https://godoc.org/github.com/PagerDuty/godspeed) for the docs
as well as some examples.

DogStatsD is a copyright of `Datadog <info@datadoghq.com>`.

## License
Godspeed is released under the BSD 3-Clause License. See the `LICENSE` file for
the full contents of the license.

## Installation
```
go get -u github.com/PagerDuty/godspeed
```

## Usage
For more details either look at the `_example_test.go` files directly or view
the examples on [GoDoc](https://godoc.org/github.com/PagerDuty/godspeed#pkg-examples).

### Emitting a gauge
```Go
g, err := godspeed.NewDefault()

if err != nil {
    // handle error
}

defer g.Conn.Close()

err = g.Gauge("example.stat", 1, nil)

if err != nil {
	// handle error
}
```

### Emitting an event
```Go
// make sure to handle the error
g, _ := godspeed.NewDefault()

defer g.Conn.Close()

title := "Nginx service restart"
text := "The Nginx service has been restarted"

// the optionals are for the optional arguments available for an event
// http://docs.datadoghq.com/guides/dogstatsd/#fields
optionals := make(map[string]string)
optionals["alert_type"] = "info"
optionals["source_type_name"] = "nginx"

addlTags := []string{"source_type:nginx"}

err := g.Event(title, text, optionals, addlTags)

if err != nil {
    fmt.Println("err:", err)
}
```

================================================
FILE: vendor/github.com/PagerDuty/godspeed/async.go
================================================
// Copyright 2014-2015 PagerDuty, Inc, et al. All rights reserved.
// Use of this source code is governed by the BSD 3-Clause
// license that can be found in the LICENSE file.

package godspeed

import "sync"

// AsyncGodspeed is used for asynchronous Godspeed calls.
// The AsyncGodspeed emission methods have an additional argument
// for a *sync.WaitGroup to have the method indicate when finished.
type AsyncGodspeed struct {
	// Godspeed is an instance of Godspeed
	Godspeed *Godspeed

	// W is a *sync.WaitGroup used for blocking application execution
	// when you want to wait for stats to be emitted.
	// This is here as a convenience, and you can use your own WaitGroup
	// in any AsyncGodspeed method calls.
	W *sync.WaitGroup
}

// NewAsync returns an instance of AsyncGodspeed. This is the more async-friendly version of Godspeed
// autoTruncate dictactes whether long stats emissions get auto-truncated or dropped. Unfortunately,
// Events will always be dropped. If you need monitor your events, you can access the Godspeed instance
// directly.
func NewAsync(host string, port int, autoTruncate bool) (a *AsyncGodspeed, err error) {
	gs, err := New(host, port, autoTruncate)

	if err != nil {
		return nil, err
	}

	a = &AsyncGodspeed{
		Godspeed: gs,
		W:        new(sync.WaitGroup),
	}

	return
}

// NewDefaultAsync is just like NewAsync except it uses the DefaultHost and DefaultPort
func NewDefaultAsync() (a *AsyncGodspeed, err error) {
	a, err = NewAsync(DefaultHost, DefaultPort, false)
	return
}

// AddTag is identical to that within the Godspeed client
func (a *AsyncGodspeed) AddTag(tag string) []string {
	return a.Godspeed.AddTag(tag)
}

// AddTags is identical to that within the Godspeed client
func (a *AsyncGodspeed) AddTags(tags []string) []string {
	return a.Godspeed.AddTags(tags)
}

// SetNamespace is identical to that within the Godspeed client
func (a *AsyncGodspeed) SetNamespace(ns string) {
	a.Godspeed.SetNamespace(ns)
}

// Event is almost identical to that within the Godspeed client
// The only chnage is that it has no return value, and takes a
// (sync.WaitGroup) argument
func (a *AsyncGodspeed) Event(title, body string, keys map[string]string, tags []string, y *sync.WaitGroup) {
	defer y.Done()

	a.Godspeed.Event(title, body, keys, tags)
}

// Send is almost identical to that within the Godspeed client
// with the addition of an argument and removal of the return value
func (a *AsyncGodspeed) Send(stat, kind string, delta, sampleRate float64, tags []string, y *sync.WaitGroup) {
	defer y.Done()

	a.Godspeed.Send(stat, kind, delta, sampleRate, tags)
}

// ServiceCheck is almost identical to that within the Godspeed client
// with the addition of an argument and removal of the return value
func (a *AsyncGodspeed) ServiceCheck(name string, status int, fields map[string]string, tags []string, y *sync.WaitGroup) {
	if y != nil {
		defer y.Done()
	}

	a.Godspeed.ServiceCheck(name, status, fields, tags)
}

// Count is almost identical to that within the Godspeed client
// As with the other AsyncGodpseed functions it omits a return value and
// takes a *sync.WaitGroup instance
func (a *AsyncGodspeed) Count(stat string, count float64, tags []string, y *sync.WaitGroup) {
	defer y.Done()

	a.Godspeed.Count(stat, count, tags)
}

// Incr is almost identical to that within the Godspeed client,
// except it has no return value and takes a *sync.WaitGroup argument.
func (a *AsyncGodspeed) Incr(stat string, tags []string, y *sync.WaitGroup) {
	defer y.Done()

	a.Godspeed.Incr(stat, tags)
}

// Decr is almost identical to that within the Godspeed client. It has
// no return value and takes a *sync.WaitGroup argument.
//
// Also, I've gotten tired of typing "Xxx is almost identical to that within..." so congrats
// on making it this far in to the docs.
func (a *AsyncGodspeed) Decr(stat string, tags []string, y *sync.WaitGroup) {
	defer y.Done()

	a.Godspeed.Decr(stat, tags)
}

// Gauge is almost identical to that within the Godspeed client.
// Here it has no return value, and takes a *sync.WaitGroup argument
func (a *AsyncGodspeed) Gauge(stat string, value float64, tags []string, y *sync.WaitGroup) {
	defer y.Done()

	a.Godspeed.Gauge(stat, value, tags)
}

// Histogram is almost identical to that within the Godspeed client.
// Within AsyncGodspeed it has no return value, and also takes a *sync.WaitGroup argument
func (a *AsyncGodspeed) Histogram(stat string, value float64, tags []string, y *sync.WaitGroup) {
	defer y.Done()

	a.Godspeed.Histogram(stat, value, tags)
}

// Timing is almost identical to that within the Godspeed client.
// The return value is removed, and it takes a *sync.WaitGroup argument here
func (a *AsyncGodspeed) Timing(stat string, value float64, tags []string, y *sync.WaitGroup) {
	defer y.Done()

	a.Godspeed.Timing(stat, value, tags)
}

// Set is almost identical to that within the Godspeed client
func (a *AsyncGodspeed) Set(stat string, value float64, tags []string, y *sync.WaitGroup) {
	defer y.Done()

	a.Godspeed.Set(stat, value, tags)
}


================================================
FILE: vendor/github.com/PagerDuty/godspeed/events.go
================================================
// Copyright 2014-2015 PagerDuty, Inc, et al. All rights reserved.
// Use of this source code is governed by the BSD 3-Clause
// license that can be found in the LICENSE file.

package godspeed

import (
	"bytes"
	"fmt"
	"strings"
)

var eventKeys = []string{"date_happened", "hostname", "aggregation_key", "priority", "source_type_name", "alert_type"}
var eventMarkers = []rune{'d', 'h', 'k', 'p', 's', 't'}

func escapeEvent(s string) string {
	return strings.NewReplacer("\n", "\\n").Replace(s)
}

func removePipes(s string) string {
	return strings.Replace(s, "|", "", -1)
}

// Event is the function for submitting a Datadog event.
// This is a Datadog-specific emission and most likely will not work on other statsd implementations.
// title and body are both strings, and are the title and body of the event respectively.
// field can be used to send the optional keys.
func (g *Godspeed) Event(title, text string, fields map[string]string, tags []string) error {
	if len(title) < 1 {
		return fmt.Errorf("title must have at least one character")
	}

	if len(text) < 1 {
		return fmt.Errorf("body must have at least one character")
	}

	var buf bytes.Buffer

	title = escapeEvent(title)
	text = escapeEvent(text)

	buf.WriteString(fmt.Sprintf("_e{%d,%d}:%v|%v", len(title), len(text), title, text))

	// if some fields were passed in convert them to their proper format
	// and write that to the buffer
	if len(fields) > 0 {
		for i, v := range eventKeys {
			if mv, ok := fields[v]; ok {
				buf.WriteString(fmt.Sprintf("|%v:%v", string(eventMarkers[i]), removePipes(mv)))
			}
		}
	}

	tags = uniqueTags(append(g.Tags, tags...))

	if len(tags) > 0 {
		for i, v := range tags {
			tags[i] = strings.Replace(v, "|", "", -1)
		}

		buf.WriteString(fmt.Sprintf("|#%v", strings.Join(tags, ",")))
	}

	// this handles the logic for truncation
	// if the buffer length is larger than the max, return an error
	// else just write it
	if bufLen := buf.Len(); bufLen > MaxBytes {
		return fmt.Errorf("error sending %v, packet larger than %d (%d)", string(title), MaxBytes, buf.Len())
	}

	_, err := g.Conn.Write(buf.Bytes())
	return err
}


================================================
FILE: vendor/github.com/PagerDuty/godspeed/godspeed.go
================================================
// Copyright 2014-2015 PagerDuty, Inc, et al. All rights reserved.
// Use of this source code is governed by the BSD 3-Clause
// license that can be found in the LICENSE file.

// Package godspeed is a statsd client for the Datadog extension of statsd
// called DogStatsD. It can be used to emit statsd stats, Datadog-specific
// events, and DogStatsD service checks. This client also has the ability to
// tag all outgoing statsd metrics. Godspeed is meant for synchronous calls,
// while AsyncGodspeed is used for what it says on the tin.
//
// The name godspeed is a bit of a rhyming slang twist on DogStatsD. It's
// also a poke at the fact that the statsd protocol's transport mechanism
// is UDP.
//
// DogStatsD is a copyright of Datadog <info@datadoghq.com>
package godspeed

import (
	"fmt"
	"net"
)

const (
	// DefaultHost is 127.0.0.1 (localhost)
	DefaultHost = "127.0.0.1"

	// DefaultPort is 8125
	DefaultPort = 8125

	// MaxBytes is the largest UDP datagram we will try to send
	MaxBytes = 8192
)

// Godspeed is an unbuffered Statsd client with compatibility geared towards the Datadog statsd format
// It consists of Conn (*net.UDPConn) object for sending metrics over UDP,
// Namespace (string) for namespacing metrics, and Tags ([]string) for tags to send with stats
type Godspeed struct {
	// Conn is the UDP connection used for sending the statsd emissions
	Conn *net.UDPConn

	// Namespace is the namespace all stats emissions are prefixed with:
	// <namespace>.<statname>
	Namespace string

	// Tags is the slice of tags to append to each stat emission
	Tags []string

	// AutoTruncate specifies whether or not we will try to truncate a stat
	// before emitting it or just return an error. This is most helpful when
	// using AsyncGodspeed. However, it can result in invalid stat being emitted
	// due to the body being truncated. Meant for when a single emission would
	// be greater than 8192 bytes.
	AutoTruncate bool
}

// New returns a new instance of a Godspeed statsd client.
// This method takes the host as a string, and port as an int.
// There is also the ability for autoTruncate. If your metric is longer than MaxBytes
// autoTruncate can be used to truncate the message instead of erroring. This doesn't work
// on events and will always return an error.
func New(host string, port int, autoTruncate bool) (g *Godspeed, err error) {
	// build a new UDP dialer
	addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", host, port))
	if err != nil {
		return nil, err
	}

	c, err := net.DialUDP("udp", nil, addr)

	// if it failed return a pointer to an empty Godspeed struct, and the error
	if err != nil {
		return nil, err
	}

	// build a new Godspeed struct with the UDPConn
	g = &Godspeed{
		Conn:         c,
		Tags:         make([]string, 0),
		AutoTruncate: autoTruncate,
	}

	return
}

// NewDefault is the same as New() except it uses DefaultHost and DefaultPort for the connection.
func NewDefault() (g *Godspeed, err error) {
	g, err = New(DefaultHost, DefaultPort, false)
	return
}

// AddTag allows you to add a tag for all future emitted stats.
// It takes the tag as a string, and returns a []string containing all Godspeed tags
func (g *Godspeed) AddTag(tag string) []string {
	// return early if the tag already exists
	for _, v := range g.Tags {
		if tag == v {
			return g.Tags
		}
	}

	// add the tag
	g.Tags = append(g.Tags, tag)

	return g.Tags
}

// AddTags is like AddTag(), except it tages a []string and adds each contained string
// This also returns a []string containing the current tags
func (g *Godspeed) AddTags(tags []string) []string {
	// if we already have tags add each tag one at a time
	// otherwise unique the list and assign it directly
	if len(g.Tags) > 0 {
		for _, tag := range tags {
			g.AddTag(tag)
		}
	} else {
		g.Tags = uniqueTags(tags)
	}

	return g.Tags
}

// SetNamespace allows you to prefix all of your metrics with a certain namespace
func (g *Godspeed) SetNamespace(ns string) {
	g.Namespace = trimReserved(ns)
}


================================================
FILE: vendor/github.com/PagerDuty/godspeed/service_checks.go
================================================
// Copyright 2014-2015 PagerDuty, Inc, et al. All rights reserved.
// Use of this source code is governed by the BSD 3-Clause
// license that can be found in the LICENSE file.

package godspeed

import (
	"bytes"
	"fmt"
	"strings"
)

var scKeys = []string{"service_check_message", "timestamp", "hostname"}
var scMark = []string{"m", "d", "h"}

// ServiceCheck is a function to emit DogStatsD service checks
// to the local DD agent. It takes the name of the service,
// which must NOT contain a pipe (|) character, and the numeric
// status for the service. The status values are the same as Nagios:
//
// OK = 0, WARNING = 1, CRITICAL = 2, UNKNOWN = 3
//
// This functionality is an extension to the statsd
// protocol by Datadog (DogStatsD):
//
// http://docs.datadoghq.com/guides/dogstatsd/#service-checks
func (g *Godspeed) ServiceCheck(name string, status int, fields map[string]string, tags []string) error {
	if len(name) == 0 {
		return fmt.Errorf("service name must have at least one character")
	}

	if status < 0 || status > 3 {
		return fmt.Errorf("unknown service status (%d); known values: 0,1,2,3", status)
	}

	if strings.ContainsAny("|", name) {
		return fmt.Errorf("service name '%s' may not include pipe character ('|')", name)
	}

	var buf bytes.Buffer

	buf.WriteString(fmt.Sprintf("_sc|%s|%d", name, status))

	if len(fields) > 0 {
		for i, v := range scKeys {
			if mv, ok := fields[v]; ok {
				buf.WriteString(fmt.Sprintf("|%s:%s", scMark[i], removePipes(mv)))
			}
		}
	}

	tags = uniqueTags(append(g.Tags, tags...))

	if len(tags) > 0 {
		for i, v := range tags {
			tags[i] = strings.Replace(v, "|", "", -1)
		}
		buf.WriteString(fmt.Sprintf("|#%s", strings.Join(tags, ",")))
	}

	if bufLen := buf.Len(); bufLen > MaxBytes {
		return fmt.Errorf("error sending %s service check, packet larger than %d (%d)", name, MaxBytes, bufLen)
	}

	_, err := g.Conn.Write(buf.Bytes())
	return err
}


================================================
FILE: vendor/github.com/PagerDuty/godspeed/shared.go
================================================
// Copyright 2014-2015 PagerDuty, Inc, et al. All rights reserved.
// Use of this source code is governed by the BSD 3-Clause
// license that can be found in the LICENSE file.

package godspeed

import "strings"

// stats names can't include :, |, or @
func trimReserved(s string) string {
	return strings.NewReplacer(":", "_", "|", "_", "@", "_").Replace(s)
}

// function to make sure tags are unique
func uniqueTags(t []string) []string {
	// if the tag slice is empty avoid allocation
	if len(t) < 1 {
		return nil
	}

	// build a map to track which values we've seen
	s := make(map[string]bool)

	// loop over each string provided
	// if the value is not in the map then replace
	// the value at t[len(s)] so that we always have
	// only unique tags at the beginning of the slice
	for i, v := range t {
		if _, x := s[v]; !x {
			// only change the value if needed
			if i != len(s) {
				t[len(s)] = v
			}

			s[v] = true
		}
	}

	// based on the size of the map we know
	// how many unique tags there were
	// so return that slice
	return []string(t[:len(s)])
}


================================================
FILE: vendor/github.com/PagerDuty/godspeed/stats.go
================================================
// Copyright 2014-2015 PagerDuty, Inc, et al. All rights reserved.
// Use of this source code is governed by the BSD 3-Clause
// license that can be found in the LICENSE file.

package godspeed

import (
	"bytes"
	"fmt"
	"math/rand"
	"strconv"
	"strings"
)

// Send is the function for emitting the metrics to statsd
// It takes the name of the stat as a string, as well as the kind.
// The kind is "g" for gauge, "c" for count, "ms" for timing, etc.
// This returns any error hit during the flushing of the stat
func (g *Godspeed) Send(stat, kind string, delta, sampleRate float64, tags []string) (err error) {
	// if the connection hasn't been set up yet
	if g.Conn == nil {
		return fmt.Errorf("socket not created")
	}

	// return if the sample rate is less than 1 and the random number is less than the sample rate
	if sampleRate < 1 && rand.Float64() >= sampleRate {
		return nil
	}

	var buffer bytes.Buffer

	// if we have a namespace write it to the byte buffer
	if len(g.Namespace) > 0 {
		buffer.WriteString(fmt.Sprintf("%v.", g.Namespace))
	}

	floatStr := strconv.FormatFloat(delta, 'f', -1, 64)

	// write the name of the metric to the byte buffer as well as the metric itself
	buffer.WriteString(fmt.Sprintf("%v:%v|%v", string(trimReserved(stat)), floatStr, kind))

	// if the sample rate is less than 1 add it too
	if sampleRate < 1 {
		floatStr = strconv.FormatFloat(sampleRate, 'f', -1, 64)
		buffer.WriteString(fmt.Sprintf("|@%v", floatStr))
	}

	// add any provided tags to the metric
	tags = uniqueTags(append(g.Tags, tags...))
	if len(tags) > 0 {
		buffer.WriteString(fmt.Sprintf("|#%v", strings.Join(tags, ",")))
	}

	// this handles the logic for truncation
	// if the buffer length is smaller than the max, just write it
	// else if AutoTruncate is enabled truncate/write the bytes
	// else generate an error to return
	if buffer.Len() <= MaxBytes {
		_, err = g.Conn.Write(buffer.Bytes())
	} else if g.AutoTruncate {
		_, err = g.Conn.Write(buffer.Bytes()[0:MaxBytes])
	} else {
		err = fmt.Errorf("error sending %v, packet larger than %d (%d)", stat, MaxBytes, buffer.Len())
	}

	return
}

// Count wraps Send() and simplifies the interface for Count stats
func (g *Godspeed) Count(stat string, count float64, tags []string) error {
	return g.Send(stat, "c", count, 1, append(g.Tags, tags...))
}

// Incr wraps Send() and simplifies the interface for incrementing a counter
// It only takes the name of the stat, and tags
func (g *Godspeed) Incr(stat string, tags []string) error {
	return g.Count(stat, 1, append(g.Tags, tags...))
}

// Decr wraps Send() and simplifies the interface for decrementing a counter
// It only takes the name of the stat, and tags
func (g *Godspeed) Decr(stat string, tags []string) error {
	return g.Count(stat, -1, append(g.Tags, tags...))
}

// Gauge wraps Send() and simplifies the interface for Gauge stats
func (g *Godspeed) Gauge(stat string, value float64, tags []string) error {
	return g.Send(stat, "g", value, 1, append(g.Tags, tags...))
}

// Histogram wraps Send() and simplifies the interface for Histogram stats
func (g *Godspeed) Histogram(stat string, value float64, tags []string) error {
	return g.Send(stat, "h", value, 1, append(g.Tags, tags...))
}

// Timing wraps Send() and simplifies the interface for Timing stats
func (g *Godspeed) Timing(stat string, value float64, tags []string) error {
	return g.Send(stat, "ms", value, 1, append(g.Tags, tags...))
}

// Set wraps Send() and simplifies the interface for Timing stats
func (g *Godspeed) Set(stat string, value float64, tags []string) error {
	return g.Send(stat, "s", value, 1, append(g.Tags, tags...))
}


================================================
FILE: vendor/github.com/bradfitz/http2/.gitignore
================================================
*~
h2i/h2i


================================================
FILE: vendor/github.com/bradfitz/http2/AUTHORS
================================================
# This file is like Go's AUTHORS file: it lists Copyright holders.
# The list of humans who have contributd is in the CONTRIBUTORS file.
#
# To contribute to this project, because it will eventually be folded
# back in to Go itself, you need to submit a CLA:
#
#    http://golang.org/doc/contribute.html#copyright
#
# Then you get added to CONTRIBUTORS and you or your company get added
# to the AUTHORS file.

Blake Mizerany <blake.mizerany@gmail.com> github=bmizerany
Daniel Morsing <daniel.morsing@gmail.com> github=DanielMorsing
Gabriel Aszalos <gabriel.aszalos@gmail.com> github=gbbr
Google, Inc.
Keith Rarick <kr@xph.us> github=kr
Matthew Keenan <tank.en.mate@gmail.com> <github@mattkeenan.net> github=mattkeenan
Matt Layher <mdlayher@gmail.com> github=mdlayher
Perry Abbott <perry.j.abbott@gmail.com> github=pabbott0
Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> github=tatsuhiro-t


================================================
FILE: vendor/github.com/bradfitz/http2/CONTRIBUTORS
================================================
# This file is like Go's CONTRIBUTORS file: it lists humans.
# The list of copyright holders (which may be companies) are in the AUTHORS file.
#
# To contribute to this project, because it will eventually be folded
# back in to Go itself, you need to submit a CLA:
#
#    http://golang.org/doc/contribute.html#copyright
#
# Then you get added to CONTRIBUTORS and you or your company get added
# to the AUTHORS file.

Blake Mizerany <blake.mizerany@gmail.com> github=bmizerany
Brad Fitzpatrick <bradfitz@golang.org> github=bradfitz
Daniel Morsing <daniel.morsing@gmail.com> github=DanielMorsing
Gabriel Aszalos <gabriel.aszalos@gmail.com> github=gbbr
Keith Rarick <kr@xph.us> github=kr
Matthew Keenan <tank.en.mate@gmail.com> <github@mattkeenan.net> github=mattkeenan
Matt Layher <mdlayher@gmail.com> github=mdlayher
Perry Abbott <perry.j.abbott@gmail.com> github=pabbott0
Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com> github=tatsuhiro-t


================================================
FILE: vendor/github.com/bradfitz/http2/Dockerfile
================================================
#
# This Dockerfile builds a recent curl with HTTP/2 client support, using
# a recent nghttp2 build.
#
# See the Makefile for how to tag it. If Docker and that image is found, the
# Go tests use this curl binary for integration tests.
#

FROM ubuntu:trusty

RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y git-core build-essential wget

RUN apt-get install -y --no-install-recommends \
       autotools-dev libtool pkg-config zlib1g-dev \
       libcunit1-dev libssl-dev libxml2-dev libevent-dev \
       automake autoconf

# Note: setting NGHTTP2_VER before the git clone, so an old git clone isn't cached:
ENV NGHTTP2_VER af24f8394e43f4
RUN cd /root && git clone https://github.com/tatsuhiro-t/nghttp2.git

WORKDIR /root/nghttp2
RUN git reset --hard $NGHTTP2_VER
RUN autoreconf -i
RUN automake
RUN autoconf
RUN ./configure
RUN make
RUN make install

WORKDIR /root
RUN wget http://curl.haxx.se/download/curl-7.40.0.tar.gz
RUN tar -zxvf curl-7.40.0.tar.gz
WORKDIR /root/curl-7.40.0
RUN ./configure --with-ssl --with-nghttp2=/usr/local
RUN make
RUN make install
RUN ldconfig

CMD ["-h"]
ENTRYPOINT ["/usr/local/bin/curl"]



================================================
FILE: vendor/github.com/bradfitz/http2/HACKING
================================================
We only accept contributions from users who have gone through Go's
contribution process (signed a CLA).

Please acknowledge whether you have (and use the same email) if
sending a pull request.


================================================
FILE: vendor/github.com/bradfitz/http2/LICENSE
================================================
Copyright 2014 Google & the Go AUTHORS

Go AUTHORS are:
See https://code.google.com/p/go/source/browse/AUTHORS

Licensed under the terms of Go itself:
https://code.google.com/p/go/source/browse/LICENSE


================================================
FILE: vendor/github.com/bradfitz/http2/Makefile
================================================
curlimage:
	docker build -t gohttp2/curl .



================================================
FILE: vendor/github.com/bradfitz/http2/README
================================================
This is a work-in-progress HTTP/2 implementation for Go.

It will eventually live in the Go standard library and won't require
any changes to your code to use.  It will just be automatic.

Status:

* The server support is pretty good. A few things are missing
  but are being worked on.
* The client work has just started but shares a lot of code
  is coming along much quicker.

Docs are at https://godoc.org/github.com/bradfitz/http2

Demo test server at https://http2.golang.org/

Help & bug reports welcome.


================================================
FILE: vendor/github.com/bradfitz/http2/buffer.go
================================================
// Copyright 2014 The Go Authors.
// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
// Licensed under the same terms as Go itself:
// https://code.google.com/p/go/source/browse/LICENSE

package http2

import (
	"errors"
)

// buffer is an io.ReadWriteCloser backed by a fixed size buffer.
// It never allocates, but moves old data as new data is written.
type buffer struct {
	buf    []byte
	r, w   int
	closed bool
	err    error // err to return to reader
}

var (
	errReadEmpty   = errors.New("read from empty buffer")
	errWriteClosed = errors.New("write on closed buffer")
	errWriteFull   = errors.New("write on full buffer")
)

// Read copies bytes from the buffer into p.
// It is an error to read when no data is available.
func (b *buffer) Read(p []byte) (n int, err error) {
	n = copy(p, b.buf[b.r:b.w])
	b.r += n
	if b.closed && b.r == b.w {
		err = b.err
	} else if b.r == b.w && n == 0 {
		err = errReadEmpty
	}
	return n, err
}

// Len returns the number of bytes of the unread portion of the buffer.
func (b *buffer) Len() int {
	return b.w - b.r
}

// Write copies bytes from p into the buffer.
// It is an error to write more data than the buffer can hold.
func (b *buffer) Write(p []byte) (n int, err error) {
	if b.closed {
		return 0, errWriteClosed
	}

	// Slide existing data to beginning.
	if b.r > 0 && len(p) > len(b.buf)-b.w {
		copy(b.buf, b.buf[b.r:b.w])
		b.w -= b.r
		b.r = 0
	}

	// Write new data.
	n = copy(b.buf[b.w:], p)
	b.w += n
	if n < len(p) {
		err = errWriteFull
	}
	return n, err
}

// Close marks the buffer as closed. Future calls to Write will
// return an error. Future calls to Read, once the buffer is
// empty, will return err.
func (b *buffer) Close(err error) {
	if !b.closed {
		b.closed = true
		b.err = err
	}
}


================================================
FILE: vendor/github.com/bradfitz/http2/errors.go
================================================
// Copyright 2014 The Go Authors.
// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
// Licensed under the same terms as Go itself:
// https://code.google.com/p/go/source/browse/LICENSE

package http2

import "fmt"

// An ErrCode is an unsigned 32-bit error code as defined in the HTTP/2 spec.
type ErrCode uint32

const (
	ErrCodeNo                 ErrCode = 0x0
	ErrCodeProtocol           ErrCode = 0x1
	ErrCodeInternal           ErrCode = 0x2
	ErrCodeFlowControl        ErrCode = 0x3
	ErrCodeSettingsTimeout    ErrCode = 0x4
	ErrCodeStreamClosed       ErrCode = 0x5
	ErrCodeFrameSize          ErrCode = 0x6
	ErrCodeRefusedStream      ErrCode = 0x7
	ErrCodeCancel             ErrCode = 0x8
	ErrCodeCompression        ErrCode = 0x9
	ErrCodeConnect            ErrCode = 0xa
	ErrCodeEnhanceYourCalm    ErrCode = 0xb
	ErrCodeInadequateSecurity ErrCode = 0xc
	ErrCodeHTTP11Required     ErrCode = 0xd
)

var errCodeName = map[ErrCode]string{
	ErrCodeNo:                 "NO_ERROR",
	ErrCodeProtocol:           "PROTOCOL_ERROR",
	ErrCodeInternal:           "INTERNAL_ERROR",
	ErrCodeFlowControl:        "FLOW_CONTROL_ERROR",
	ErrCodeSettingsTimeout:    "SETTINGS_TIMEOUT",
	ErrCodeStreamClosed:       "STREAM_CLOSED",
	ErrCodeFrameSize:          "FRAME_SIZE_ERROR",
	ErrCodeRefusedStream:      "REFUSED_STREAM",
	ErrCodeCancel:             "CANCEL",
	ErrCodeCompression:        "COMPRESSION_ERROR",
	ErrCodeConnect:            "CONNECT_ERROR",
	ErrCodeEnhanceYourCalm:    "ENHANCE_YOUR_CALM",
	ErrCodeInadequateSecurity: "INADEQUATE_SECURITY",
	ErrCodeHTTP11Required:     "HTTP_1_1_REQUIRED",
}

func (e ErrCode) String() string {
	if s, ok := errCodeName[e]; ok {
		return s
	}
	return fmt.Sprintf("unknown error code 0x%x", uint32(e))
}

// ConnectionError is an error that results in the termination of the
// entire connection.
type ConnectionError ErrCode

func (e ConnectionError) Error() string { return fmt.Sprintf("connection error: %s", ErrCode(e)) }

// StreamError is an error that only affects one stream within an
// HTTP/2 connection.
type StreamError struct {
	StreamID uint32
	Code     ErrCode
}

func (e StreamError) Error() string {
	return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code)
}

// 6.9.1 The Flow Control Window
// "If a sender receives a WINDOW_UPDATE that causes a flow control
// window to exceed this maximum it MUST terminate either the stream
// or the connection, as appropriate. For streams, [...]; for the
// connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code."
type goAwayFlowError struct{}

func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }


================================================
FILE: vendor/github.com/bradfitz/http2/flow.go
================================================
// Copyright 2014 The Go Authors.
// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
// Licensed under the same terms as Go itself:
// https://code.google.com/p/go/source/browse/LICENSE

// Flow control

package http2

// flow is the flow control window's size.
type flow struct {
	// n is the number of DATA bytes we're allowed to send.
	// A flow is kept both on a conn and a per-stream.
	n int32

	// conn points to the shared connection-level flow that is
	// shared by all streams on that conn. It is nil for the flow
	// that's on the conn directly.
	conn *flow
}

func (f *flow) setConnFlow(cf *flow) { f.conn = cf }

func (f *flow) available() int32 {
	n := f.n
	if f.conn != nil && f.conn.n < n {
		n = f.conn.n
	}
	return n
}

func (f *flow) take(n int32) {
	if n > f.available() {
		panic("internal error: took too much")
	}
	f.n -= n
	if f.conn != nil {
		f.conn.n -= n
	}
}

// add adds n bytes (positive or negative) to the flow control window.
// It returns false if the sum would exceed 2^31-1.
func (f *flow) add(n int32) bool {
	remain := (1<<31 - 1) - f.n
	if n > remain {
		return false
	}
	f.n += n
	return true
}


================================================
FILE: vendor/github.com/bradfitz/http2/frame.go
================================================
// Copyright 2014 The Go Authors.
// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
// Licensed under the same terms as Go itself:
// https://code.google.com/p/go/source/browse/LICENSE

package http2

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"sync"
)

const frameHeaderLen = 9

var padZeros = make([]byte, 255) // zeros for padding

// A FrameType is a registered frame type as defined in
// http://http2.github.io/http2-spec/#rfc.section.11.2
type FrameType uint8

const (
	FrameData         FrameType = 0x0
	FrameHeaders      FrameType = 0x1
	FramePriority     FrameType = 0x2
	FrameRSTStream    FrameType = 0x3
	FrameSettings     FrameType = 0x4
	FramePushPromise  FrameType = 0x5
	FramePing         FrameType = 0x6
	FrameGoAway       FrameType = 0x7
	FrameWindowUpdate FrameType = 0x8
	FrameContinuation FrameType = 0x9
)

var frameName = map[FrameType]string{
	FrameData:         "DATA",
	FrameHeaders:      "HEADERS",
	FramePriority:     "PRIORITY",
	FrameRSTStream:    "RST_STREAM",
	FrameSettings:     "SETTINGS",
	FramePushPromise:  "PUSH_PROMISE",
	FramePing:         "PING",
	FrameGoAway:       "GOAWAY",
	FrameWindowUpdate: "WINDOW_UPDATE",
	FrameContinuation: "CONTINUATION",
}

func (t FrameType) String() string {
	if s, ok := frameName[t]; ok {
		return s
	}
	return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8(t))
}

// Flags is a bitmask of HTTP/2 flags.
// The meaning of flags varies depending on the frame type.
type Flags uint8

// Has reports whether f contains all (0 or more) flags in v.
func (f Flags) Has(v Flags) bool {
	return (f & v) == v
}

// Frame-specific FrameHeader flag bits.
const (
	// Data Frame
	FlagDataEndStream Flags = 0x1
	FlagDataPadded    Flags = 0x8

	// Headers Frame
	FlagHeadersEndStream  Flags = 0x1
	FlagHeadersEndHeaders Flags = 0x4
	FlagHeadersPadded     Flags = 0x8
	FlagHeadersPriority   Flags = 0x20

	// Settings Frame
	FlagSettingsAck Flags = 0x1

	// Ping Frame
	FlagPingAck Flags = 0x1

	// Continuation Frame
	FlagContinuationEndHeaders Flags = 0x4

	FlagPushPromiseEndHeaders Flags = 0x4
	FlagPushPromisePadded     Flags = 0x8
)

var flagName = map[FrameType]map[Flags]string{
	FrameData: {
		FlagDataEndStream: "END_STREAM",
		FlagDataPadded:    "PADDED",
	},
	FrameHeaders: {
		FlagHeadersEndStream:  "END_STREAM",
		FlagHeadersEndHeaders: "END_HEADERS",
		FlagHeadersPadded:     "PADDED",
		FlagHeadersPriority:   "PRIORITY",
	},
	FrameSettings: {
		FlagSettingsAck: "ACK",
	},
	FramePing: {
		FlagPingAck: "ACK",
	},
	FrameContinuation: {
		FlagContinuationEndHeaders: "END_HEADERS",
	},
	FramePushPromise: {
		FlagPushPromiseEndHeaders: "END_HEADERS",
		FlagPushPromisePadded:     "PADDED",
	},
}

// a frameParser parses a frame given its FrameHeader and payload
// bytes. The length of payload will always equal fh.Length (which
// might be 0).
type frameParser func(fh FrameHeader, payload []byte) (Frame, error)

var frameParsers = map[FrameType]frameParser{
	FrameData:         parseDataFrame,
	FrameHeaders:      parseHeadersFrame,
	FramePriority:     parsePriorityFrame,
	FrameRSTStream:    parseRSTStreamFrame,
	FrameSettings:     parseSettingsFrame,
	FramePushPromise:  parsePushPromise,
	FramePing:         parsePingFrame,
	FrameGoAway:       parseGoAwayFrame,
	FrameWindowUpdate: parseWindowUpdateFrame,
	FrameContinuation: parseContinuationFrame,
}

func typeFrameParser(t FrameType) frameParser {
	if f := frameParsers[t]; f != nil {
		return f
	}
	return parseUnknownFrame
}

// A FrameHeader is the 9 byte header of all HTTP/2 frames.
//
// See http://http2.github.io/http2-spec/#FrameHeader
type FrameHeader struct {
	valid bool // caller can access []byte fields in the Frame

	// Type is the 1 byte frame type. There are ten standard frame
	// types, but extension frame types may be written by WriteRawFrame
	// and will be returned by ReadFrame (as UnknownFrame).
	Type FrameType

	// Flags are the 1 byte of 8 potential bit flags per frame.
	// They are specific to the frame type.
	Flags Flags

	// Length is the length of the frame, not including the 9 byte header.
	// The maximum size is one byte less than 16MB (uint24), but only
	// frames up to 16KB are allowed without peer agreement.
	Length uint32

	// StreamID is which stream this frame is for. Certain frames
	// are not stream-specific, in which case this field is 0.
	StreamID uint32
}

// Header returns h. It exists so FrameHeaders can be embedded in other
// specific frame types and implement the Frame interface.
func (h FrameHeader) Header() FrameHeader { return h }

func (h FrameHeader) String() string {
	var buf bytes.Buffer
	buf.WriteString("[FrameHeader ")
	buf.WriteString(h.Type.String())
	if h.Flags != 0 {
		buf.WriteString(" flags=")
		set := 0
		for i := uint8(0); i < 8; i++ {
			if h.Flags&(1<<i) == 0 {
				continue
			}
			set++
			if set > 1 {
				buf.WriteByte('|')
			}
			name := flagName[h.Type][Flags(1<<i)]
			if name != "" {
				buf.WriteString(name)
			} else {
				fmt.Fprintf(&buf, "0x%x", 1<<i)
			}
		}
	}
	if h.StreamID != 0 {
		fmt.Fprintf(&buf, " stream=%d", h.StreamID)
	}
	fmt.Fprintf(&buf, " len=%d]", h.Length)
	return buf.String()
}

func (h *FrameHeader) checkValid() {
	if !h.valid {
		panic("Frame accessor called on non-owned Frame")
	}
}

func (h *FrameHeader) invalidate() { h.valid = false }

// frame header bytes.
// Used only by ReadFrameHeader.
var fhBytes = sync.Pool{
	New: func() interface{} {
		buf := make([]byte, frameHeaderLen)
		return &buf
	},
}

// ReadFrameHeader reads 9 bytes from r and returns a FrameHeader.
// Most users should use Framer.ReadFrame instead.
func ReadFrameHeader(r io.Reader) (FrameHeader, error) {
	bufp := fhBytes.Get().(*[]byte)
	defer fhBytes.Put(bufp)
	return readFrameHeader(*bufp, r)
}

func readFrameHeader(buf []byte, r io.Reader) (FrameHeader, error) {
	_, err := io.ReadFull(r, buf[:frameHeaderLen])
	if err != nil {
		return FrameHeader{}, err
	}
	return FrameHeader{
		Length:   (uint32(buf[0])<<16 | uint32(buf[1])<<8 | uint32(buf[2])),
		Type:     FrameType(buf[3]),
		Flags:    Flags(buf[4]),
		StreamID: binary.BigEndian.Uint32(buf[5:]) & (1<<31 - 1),
		valid:    true,
	}, nil
}

// A Frame is the base interface implemented by all frame types.
// Callers will generally type-assert the specific frame type:
// *HeadersFrame, *SettingsFrame, *WindowUpdateFrame, etc.
//
// Frames are only valid until the next call to Framer.ReadFrame.
type Frame interface {
	Header() FrameHeader

	// invalidate is called by Framer.ReadFrame to make this
	// frame's buffers as being invalid, since the subsequent
	// frame will reuse them.
	invalidate()
}

// A Framer reads and writes Frames.
type Framer struct {
	r         io.Reader
	lastFrame Frame

	maxReadSize uint32
	headerBuf   [frameHeaderLen]byte

	// TODO: let getReadBuf be configurable, and use a less memory-pinning
	// allocator in server.go to minimize memory pinned for many idle conns.
	// Will probably also need to make frame invalidation have a hook too.
	getReadBuf func(size uint32) []byte
	readBuf    []byte // cache for default getReadBuf

	maxWriteSize uint32 // zero means unlimited; TODO: implement

	w    io.Writer
	wbuf []byte

	// AllowIllegalWrites permits the Framer's Write methods to
	// write frames that do not conform to the HTTP/2 spec.  This
	// permits using the Framer to test other HTTP/2
	// implementations' conformance to the spec.
	// If false, the Write methods will prefer to return an error
	// rather than comply.
	AllowIllegalWrites bool

	// TODO: track which type of frame & with which flags was sent
	// last.  Then return an error (unless AllowIllegalWrites) if
	// we're in the middle of a header block and a
	// non-Continuation or Continuation on a different stream is
	// attempted to be written.
}

func (f *Framer) startWrite(ftype FrameType, flags Flags, streamID uint32) {
	// Write the FrameHeader.
	f.wbuf = append(f.wbuf[:0],
		0, // 3 bytes of length, filled in in endWrite
		0,
		0,
		byte(ftype),
		byte(flags),
		byte(streamID>>24),
		byte(streamID>>16),
		byte(streamID>>8),
		byte(streamID))
}

func (f *Framer) endWrite() error {
	// Now that we know the final size, fill in the FrameHeader in
	// the space previously reserved for it. Abuse append.
	length := len(f.wbuf) - frameHeaderLen
	if length >= (1 << 24) {
		return ErrFrameTooLarge
	}
	_ = append(f.wbuf[:0],
		byte(length>>16),
		byte(length>>8),
		byte(length))
	n, err := f.w.Write(f.wbuf)
	if err == nil && n != len(f.wbuf) {
		err = io.ErrShortWrite
	}
	return err
}

func (f *Framer) writeByte(v byte)     { f.wbuf = append(f.wbuf, v) }
func (f *Framer) writeBytes(v []byte)  { f.wbuf = append(f.wbuf, v...) }
func (f *Framer) writeUint16(v uint16) { f.wbuf = append(f.wbuf, byte(v>>8), byte(v)) }
func (f *Framer) writeUint32(v uint32) {
	f.wbuf = append(f.wbuf, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
}

const (
	minMaxFrameSize = 1 << 14
	maxFrameSize    = 1<<24 - 1
)

// NewFramer returns a Framer that writes frames to w and reads them from r.
func NewFramer(w io.Writer, r io.Reader) *Framer {
	fr := &Framer{
		w: w,
		r: r,
	}
	fr.getReadBuf = func(size uint32) []byte {
		if cap(fr.readBuf) >= int(size) {
			return fr.readBuf[:size]
		}
		fr.readBuf = make([]byte, size)
		return fr.readBuf
	}
	fr.SetMaxReadFrameSize(maxFrameSize)
	return fr
}

// SetMaxReadFrameSize sets the maximum size of a frame
// that will be read by a subsequent call to ReadFrame.
// It is the caller's responsibility to advertise this
// limit with a SETTINGS frame.
func (fr *Framer) SetMaxReadFrameSize(v uint32) {
	if v > maxFrameSize {
		v = maxFrameSize
	}
	fr.maxReadSize = v
}

// ErrFrameTooLarge is returned from Framer.ReadFrame when the peer
// sends a frame that is larger than declared with SetMaxReadFrameSize.
var ErrFrameTooLarge = errors.New("http2: frame too large")

// ReadFrame reads a single frame. The returned Frame is only valid
// until the next call to ReadFrame.
// If the frame is larger than previously set with SetMaxReadFrameSize,
// the returned error is ErrFrameTooLarge.
func (fr *Framer) ReadFrame() (Frame, error) {
	if fr.lastFrame != nil {
		fr.lastFrame.invalidate()
	}
	fh, err := readFrameHeader(fr.headerBuf[:], fr.r)
	if err != nil {
		return nil, err
	}
	if fh.Length > fr.maxReadSize {
		return nil, ErrFrameTooLarge
	}
	payload := fr.getReadBuf(fh.Length)
	if _, err := io.ReadFull(fr.r, payload); err != nil {
		return nil, err
	}
	f, err := typeFrameParser(fh.Type)(fh, payload)
	if err != nil {
		return nil, err
	}
	fr.lastFrame = f
	return f, nil
}

// A DataFrame conveys arbitrary, variable-length sequences of octets
// associated with a stream.
// See http://http2.github.io/http2-spec/#rfc.section.6.1
type DataFrame struct {
	FrameHeader
	data []byte
}

func (f *DataFrame) StreamEnded() bool {
	return f.FrameHeader.Flags.Has(FlagDataEndStream)
}

// Data returns the frame's data octets, not including any padding
// size byte or padding suffix bytes.
// The caller must not retain the returned memory past the next
// call to ReadFrame.
func (f *DataFrame) Data() []byte {
	f.checkValid()
	return f.data
}

func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) {
	if fh.StreamID == 0 {
		// DATA frames MUST be associated with a stream. If a
		// DATA frame is received whose stream identifier
		// field is 0x0, the recipient MUST respond with a
		// connection error (Section 5.4.1) of type
		// PROTOCOL_ERROR.
		return nil, ConnectionError(ErrCodeProtocol)
	}
	f := &DataFrame{
		FrameHeader: fh,
	}
	var padSize byte
	if fh.Flags.Has(FlagDataPadded) {
		var err error
		payload, padSize, err = readByte(payload)
		if err != nil {
			return nil, err
		}
	}
	if int(padSize) > len(payload) {
		// If the length of the padding is greater than the
		// length of the frame payload, the recipient MUST
		// treat this as a connection error.
		// Filed: https://github.com/http2/http2-spec/issues/610
		return nil, ConnectionError(ErrCodeProtocol)
	}
	f.data = payload[:len(payload)-int(padSize)]
	return f, nil
}

var errStreamID = errors.New("invalid streamid")

func validStreamID(streamID uint32) bool {
	return streamID != 0 && streamID&(1<<31) == 0
}

// WriteData writes a DATA frame.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
	// TODO: ignoring padding for now. will add when somebody cares.
	if !validStreamID(streamID) && !f.AllowIllegalWrites {
		return errStreamID
	}
	var flags Flags
	if endStream {
		flags |= FlagDataEndStream
	}
	f.startWrite(FrameData, flags, streamID)
	f.wbuf = append(f.wbuf, data...)
	return f.endWrite()
}

// A SettingsFrame conveys configuration parameters that affect how
// endpoints communicate, such as preferences and constraints on peer
// behavior.
//
// See http://http2.github.io/http2-spec/#SETTINGS
type SettingsFrame struct {
	FrameHeader
	p []byte
}

func parseSettingsFrame(fh FrameHeader, p []byte) (Frame, error) {
	if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
		// When this (ACK 0x1) bit is set, the payload of the
		// SETTINGS frame MUST be empty.  Receipt of a
		// SETTINGS frame with the ACK flag set and a length
		// field value other than 0 MUST be treated as a
		// connection error (Section 5.4.1) of type
		// FRAME_SIZE_ERROR.
		return nil, ConnectionError(ErrCodeFrameSize)
	}
	if fh.StreamID != 0 {
		// SETTINGS frames always apply to a connection,
		// never a single stream.  The stream identifier for a
		// SETTINGS frame MUST be zero (0x0).  If an endpoint
		// receives a SETTINGS frame whose stream identifier
		// field is anything other than 0x0, the endpoint MUST
		// respond with a connection error (Section 5.4.1) of
		// type PROTOCOL_ERROR.
		return nil, ConnectionError(ErrCodeProtocol)
	}
	if len(p)%6 != 0 {
		// Expecting even number of 6 byte settings.
		return nil, ConnectionError(ErrCodeFrameSize)
	}
	f := &SettingsFrame{FrameHeader: fh, p: p}
	if v, ok := f.Value(SettingInitialWindowSize); ok && v > (1<<31)-1 {
		// Values above the maximum flow control window size of 2^31 - 1 MUST
		// be treated as a connection error (Section 5.4.1) of type
		// FLOW_CONTROL_ERROR.
		return nil, ConnectionError(ErrCodeFlowControl)
	}
	return f, nil
}

func (f *SettingsFrame) IsAck() bool {
	return f.FrameHeader.Flags.Has(FlagSettingsAck)
}

func (f *SettingsFrame) Value(s SettingID) (v uint32, ok bool) {
	f.checkValid()
	buf := f.p
	for len(buf) > 0 {
		settingID := SettingID(binary.BigEndian.Uint16(buf[:2]))
		if settingID == s {
			return binary.BigEndian.Uint32(buf[2:6]), true
		}
		buf = buf[6:]
	}
	return 0, false
}

// ForeachSetting runs fn for each setting.
// It stops and returns the first error.
func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error {
	f.checkValid()
	buf := f.p
	for len(buf) > 0 {
		if err := fn(Setting{
			SettingID(binary.BigEndian.Uint16(buf[:2])),
			binary.BigEndian.Uint32(buf[2:6]),
		}); err != nil {
			return err
		}
		buf = buf[6:]
	}
	return nil
}

// WriteSettings writes a SETTINGS frame with zero or more settings
// specified and the ACK bit not set.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func (f *Framer) WriteSettings(settings ...Setting) error {
	f.startWrite(FrameSettings, 0, 0)
	for _, s := range settings {
		f.writeUint16(uint16(s.ID))
		f.writeUint32(s.Val)
	}
	return f.endWrite()
}

// WriteSettings writes an empty SETTINGS frame with the ACK bit set.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func (f *Framer) WriteSettingsAck() error {
	f.startWrite(FrameSettings, FlagSettingsAck, 0)
	return f.endWrite()
}

// A PingFrame is a mechanism for measuring a minimal round trip time
// from the sender, as well as determining whether an idle connection
// is still functional.
// See http://http2.github.io/http2-spec/#rfc.section.6.7
type PingFrame struct {
	FrameHeader
	Data [8]byte
}

func parsePingFrame(fh FrameHeader, payload []byte) (Frame, error) {
	if len(payload) != 8 {
		return nil, ConnectionError(ErrCodeFrameSize)
	}
	if fh.StreamID != 0 {
		return nil, ConnectionError(ErrCodeProtocol)
	}
	f := &PingFrame{FrameHeader: fh}
	copy(f.Data[:], payload)
	return f, nil
}

func (f *Framer) WritePing(ack bool, data [8]byte) error {
	var flags Flags
	if ack {
		flags = FlagPingAck
	}
	f.startWrite(FramePing, flags, 0)
	f.writeBytes(data[:])
	return f.endWrite()
}

// A GoAwayFrame informs the remote peer to stop creating streams on this connection.
// See http://http2.github.io/http2-spec/#rfc.section.6.8
type GoAwayFrame struct {
	FrameHeader
	LastStreamID uint32
	ErrCode      ErrCode
	debugData    []byte
}

// DebugData returns any debug data in the GOAWAY frame. Its contents
// are not defined.
// The caller must not retain the returned memory past the next
// call to ReadFrame.
func (f *GoAwayFrame) DebugData() []byte {
	f.checkValid()
	return f.debugData
}

func parseGoAwayFrame(fh FrameHeader, p []byte) (Frame, error) {
	if fh.StreamID != 0 {
		return nil, ConnectionError(ErrCodeProtocol)
	}
	if len(p) < 8 {
		return nil, ConnectionError(ErrCodeFrameSize)
	}
	return &GoAwayFrame{
		FrameHeader:  fh,
		LastStreamID: binary.BigEndian.Uint32(p[:4]) & (1<<31 - 1),
		ErrCode:      ErrCode(binary.BigEndian.Uint32(p[4:8])),
		debugData:    p[8:],
	}, nil
}

func (f *Framer) WriteGoAway(maxStreamID uint32, code ErrCode, debugData []byte) error {
	f.startWrite(FrameGoAway, 0, 0)
	f.writeUint32(maxStreamID & (1<<31 - 1))
	f.writeUint32(uint32(code))
	f.writeBytes(debugData)
	return f.endWrite()
}

// An UnknownFrame is the frame type returned when the frame type is unknown
// or no specific frame type parser exists.
type UnknownFrame struct {
	FrameHeader
	p []byte
}

// Payload returns the frame's payload (after the header).  It is not
// valid to call this method after a subsequent call to
// Framer.ReadFrame, nor is it valid to retain the returned slice.
// The memory is owned by the Framer and is invalidated when the next
// frame is read.
func (f *UnknownFrame) Payload() []byte {
	f.checkValid()
	return f.p
}

func parseUnknownFrame(fh FrameHeader, p []byte) (Frame, error) {
	return &UnknownFrame{fh, p}, nil
}

// A WindowUpdateFrame is used to implement flow control.
// See http://http2.github.io/http2-spec/#rfc.section.6.9
type WindowUpdateFrame struct {
	FrameHeader
	Increment uint32
}

func parseWindowUpdateFrame(fh FrameHeader, p []byte) (Frame, error) {
	if len(p) != 4 {
		return nil, ConnectionError(ErrCodeFrameSize)
	}
	inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff // mask off high reserved bit
	if inc == 0 {
		// A receiver MUST treat the receipt of a
		// WINDOW_UPDATE frame with an flow control window
		// increment of 0 as a stream error (Section 5.4.2) of
		// type PROTOCOL_ERROR; errors on the connection flow
		// control window MUST be treated as a connection
		// error (Section 5.4.1).
		if fh.StreamID == 0 {
			return nil, ConnectionError(ErrCodeProtocol)
		}
		return nil, StreamError{fh.StreamID, ErrCodeProtocol}
	}
	return &WindowUpdateFrame{
		FrameHeader: fh,
		Increment:   inc,
	}, nil
}

// WriteWindowUpdate writes a WINDOW_UPDATE frame.
// The increment value must be between 1 and 2,147,483,647, inclusive.
// If the Stream ID is zero, the window update applies to the
// connection as a whole.
func (f *Framer) WriteWindowUpdate(streamID, incr uint32) error {
	// "The legal range for the increment to the flow control window is 1 to 2^31-1 (2,147,483,647) octets."
	if (incr < 1 || incr > 2147483647) && !f.AllowIllegalWrites {
		return errors.New("illegal window increment value")
	}
	f.startWrite(FrameWindowUpdate, 0, streamID)
	f.writeUint32(incr)
	return f.endWrite()
}

// A HeadersFrame is used to open a stream and additionally carries a
// header block fragment.
type HeadersFrame struct {
	FrameHeader

	// Priority is set if FlagHeadersPriority is set in the FrameHeader.
	Priority PriorityParam

	headerFragBuf []byte // not owned
}

func (f *HeadersFrame) HeaderBlockFragment() []byte {
	f.checkValid()
	return f.headerFragBuf
}

func (f *HeadersFrame) HeadersEnded() bool {
	return f.FrameHeader.Flags.Has(FlagHeadersEndHeaders)
}

func (f *HeadersFrame) StreamEnded() bool {
	return f.FrameHeader.Flags.Has(FlagHeadersEndStream)
}

func (f *HeadersFrame) HasPriority() bool {
	return f.FrameHeader.Flags.Has(FlagHeadersPriority)
}

func parseHeadersFrame(fh FrameHeader, p []byte) (_ Frame, err error) {
	hf := &HeadersFrame{
		FrameHeader: fh,
	}
	if fh.StreamID == 0 {
		// HEADERS frames MUST be associated with a stream.  If a HEADERS frame
		// is received whose stream identifier field is 0x0, the recipient MUST
		// respond with a connection error (Section 5.4.1) of type
		// PROTOCOL_ERROR.
		return nil, ConnectionError(ErrCodeProtocol)
	}
	var padLength uint8
	if fh.Flags.Has(FlagHeadersPadded) {
		if p, padLength, err = readByte(p); err != nil {
			return
		}
	}
	if fh.Flags.Has(FlagHeadersPriority) {
		var v uint32
		p, v, err = readUint32(p)
		if err != nil {
			return nil, err
		}
		hf.Priority.StreamDep = v & 0x7fffffff
		hf.Priority.Exclusive = (v != hf.Priority.StreamDep) // high bit was set
		p, hf.Priority.Weight, err = readByte(p)
		if err != nil {
			return nil, err
		}
	}
	if len(p)-int(padLength) <= 0 {
		return nil, StreamError{fh.StreamID, ErrCodeProtocol}
	}
	hf.headerFragBuf = p[:len(p)-int(padLength)]
	return hf, nil
}

// HeadersFrameParam are the parameters for writing a HEADERS frame.
type HeadersFrameParam struct {
	// StreamID is the required Stream ID to initiate.
	StreamID uint32
	// BlockFragment is part (or all) of a Header Block.
	BlockFragment []byte

	// EndStream indicates that the header block is the last that
	// the endpoint will send for the identified stream. Setting
	// this flag causes the stream to enter one of "half closed"
	// states.
	EndStream bool

	// EndHeaders indicates that this frame contains an entire
	// header block and is not followed by any
	// CONTINUATION frames.
	EndHeaders bool

	// PadLength is the optional number of bytes of zeros to add
	// to this frame.
	PadLength uint8

	// Priority, if non-zero, includes stream priority information
	// in the HEADER frame.
	Priority PriorityParam
}

// WriteHeaders writes a single HEADERS frame.
//
// This is a low-level header writing method. Encoding headers and
// splitting them into any necessary CONTINUATION frames is handled
// elsewhere.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func (f *Framer) WriteHeaders(p HeadersFrameParam) error {
	if !validStreamID(p.StreamID) && !f.AllowIllegalWrites {
		return errStreamID
	}
	var flags Flags
	if p.PadLength != 0 {
		flags |= FlagHeadersPadded
	}
	if p.EndStream {
		flags |= FlagHeadersEndStream
	}
	if p.EndHeaders {
		flags |= FlagHeadersEndHeaders
	}
	if !p.Priority.IsZero() {
		flags |= FlagHeadersPriority
	}
	f.startWrite(FrameHeaders, flags, p.StreamID)
	if p.PadLength != 0 {
		f.writeByte(p.PadLength)
	}
	if !p.Priority.IsZero() {
		v := p.Priority.StreamDep
		if !validStreamID(v) && !f.AllowIllegalWrites {
			return errors.New("invalid dependent stream id")
		}
		if p.Priority.Exclusive {
			v |= 1 << 31
		}
		f.writeUint32(v)
		f.writeByte(p.Priority.Weight)
	}
	f.wbuf = append(f.wbuf, p.BlockFragment...)
	f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...)
	return f.endWrite()
}

// A PriorityFrame specifies the sender-advised priority of a stream.
// See http://http2.github.io/http2-spec/#rfc.section.6.3
type PriorityFrame struct {
	FrameHeader
	PriorityParam
}

// PriorityParam are the stream prioritzation parameters.
type PriorityParam struct {
	// StreamDep is a 31-bit stream identifier for the
	// stream that this stream depends on. Zero means no
	// dependency.
	StreamDep uint32

	// Exclusive is whether the dependency is exclusive.
	Exclusive bool

	// Weight is the stream's zero-indexed weight. It should be
	// set together with StreamDep, or neither should be set.  Per
	// the spec, "Add one to the value to obtain a weight between
	// 1 and 256."
	Weight uint8
}

func (p PriorityParam) IsZero() bool {
	return p == PriorityParam{}
}

func parsePriorityFrame(fh FrameHeader, payload []byte) (Frame, error) {
	if fh.StreamID == 0 {
		return nil, ConnectionError(ErrCodeProtocol)
	}
	if len(payload) != 5 {
		return nil, ConnectionError(ErrCodeFrameSize)
	}
	v := binary.BigEndian.Uint32(payload[:4])
	streamID := v & 0x7fffffff // mask off high bit
	return &PriorityFrame{
		FrameHeader: fh,
		PriorityParam: PriorityParam{
			Weight:    payload[4],
			StreamDep: streamID,
			Exclusive: streamID != v, // was high bit set?
		},
	}, nil
}

// WritePriority writes a PRIORITY frame.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func (f *Framer) WritePriority(streamID uint32, p PriorityParam) error {
	if !validStreamID(streamID) && !f.AllowIllegalWrites {
		return errStreamID
	}
	f.startWrite(FramePriority, 0, streamID)
	v := p.StreamDep
	if p.Exclusive {
		v |= 1 << 31
	}
	f.writeUint32(v)
	f.writeByte(p.Weight)
	return f.endWrite()
}

// A RSTStreamFrame allows for abnormal termination of a stream.
// See http://http2.github.io/http2-spec/#rfc.section.6.4
type RSTStreamFrame struct {
	FrameHeader
	ErrCode ErrCode
}

func parseRSTStreamFrame(fh FrameHeader, p []byte) (Frame, error) {
	if len(p) != 4 {
		return nil, ConnectionError(ErrCodeFrameSize)
	}
	if fh.StreamID == 0 {
		return nil, ConnectionError(ErrCodeProtocol)
	}
	return &RSTStreamFrame{fh, ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil
}

// WriteRSTStream writes a RST_STREAM frame.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func (f *Framer) WriteRSTStream(streamID uint32, code ErrCode) error {
	if !validStreamID(streamID) && !f.AllowIllegalWrites {
		return errStreamID
	}
	f.startWrite(FrameRSTStream, 0, streamID)
	f.writeUint32(uint32(code))
	return f.endWrite()
}

// A ContinuationFrame is used to continue a sequence of header block fragments.
// See http://http2.github.io/http2-spec/#rfc.section.6.10
type ContinuationFrame struct {
	FrameHeader
	headerFragBuf []byte
}

func parseContinuationFrame(fh FrameHeader, p []byte) (Frame, error) {
	return &ContinuationFrame{fh, p}, nil
}

func (f *ContinuationFrame) StreamEnded() bool {
	return f.FrameHeader.Flags.Has(FlagDataEndStream)
}

func (f *ContinuationFrame) HeaderBlockFragment() []byte {
	f.checkValid()
	return f.headerFragBuf
}

func (f *ContinuationFrame) HeadersEnded() bool {
	return f.FrameHeader.Flags.Has(FlagContinuationEndHeaders)
}

// WriteContinuation writes a CONTINUATION frame.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func (f *Framer) WriteContinuation(streamID uint32, endHeaders bool, headerBlockFragment []byte) error {
	if !validStreamID(streamID) && !f.AllowIllegalWrites {
		return errStreamID
	}
	var flags Flags
	if endHeaders {
		flags |= FlagContinuationEndHeaders
	}
	f.startWrite(FrameContinuation, flags, streamID)
	f.wbuf = append(f.wbuf, headerBlockFragment...)
	return f.endWrite()
}

// A PushPromiseFrame is used to initiate a server stream.
// See http://http2.github.io/http2-spec/#rfc.section.6.6
type PushPromiseFrame struct {
	FrameHeader
	PromiseID     uint32
	headerFragBuf []byte // not owned
}

func (f *PushPromiseFrame) HeaderBlockFragment() []byte {
	f.checkValid()
	return f.headerFragBuf
}

func (f *PushPromiseFrame) HeadersEnded() bool {
	return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
}

func parsePushPromise(fh FrameHeader, p []byte) (_ Frame, err error) {
	pp := &PushPromiseFrame{
		FrameHeader: fh,
	}
	if pp.StreamID == 0 {
		// PUSH_PROMISE frames MUST be associated with an existing,
		// peer-initiated stream. The stream identifier of a
		// PUSH_PROMISE frame indicates the stream it is associated
		// with. If the stream identifier field specifies the value
		// 0x0, a recipient MUST respond with a connection error
		// (Section 5.4.1) of type PROTOCOL_ERROR.
		return nil, ConnectionError(ErrCodeProtocol)
	}
	// The PUSH_PROMISE frame includes optional padding.
	// Padding fields and flags are identical to those defined for DATA frames
	var padLength uint8
	if fh.Flags.Has(FlagPushPromisePadded) {
		if p, padLength, err = readByte(p); err != nil {
			return
		}
	}

	p, pp.PromiseID, err = readUint32(p)
	if err != nil {
		return
	}
	pp.PromiseID = pp.PromiseID & (1<<31 - 1)

	if int(padLength) > len(p) {
		// like the DATA frame, error out if padding is longer than the body.
		return nil, ConnectionError(ErrCodeProtocol)
	}
	pp.headerFragBuf = p[:len(p)-int(padLength)]
	return pp, nil
}

// PushPromiseParam are the parameters for writing a PUSH_PROMISE frame.
type PushPromiseParam struct {
	// StreamID is the required Stream ID to initiate.
	StreamID uint32

	// PromiseID is the required Stream ID which this
	// Push Promises
	PromiseID uint32

	// BlockFragment is part (or all) of a Header Block.
	BlockFragment []byte

	// EndHeaders indicates that this frame contains an entire
	// header block and is not followed by any
	// CONTINUATION frames.
	EndHeaders bool

	// PadLength is the optional number of bytes of zeros to add
	// to this frame.
	PadLength uint8
}

// WritePushPromise writes a single PushPromise Frame.
//
// As with Header Frames, This is the low level call for writing
// individual frames. Continuation frames are handled elsewhere.
//
// It will perform exactly one Write to the underlying Writer.
// It is the caller's responsibility to not call other Write methods concurrently.
func (f *Framer) WritePushPromise(p PushPromiseParam) error {
	if !validStreamID(p.StreamID) && !f.AllowIllegalWrites {
		return errStreamID
	}
	var flags Flags
	if p.PadLength != 0 {
		flags |= FlagPushPromisePadded
	}
	if p.EndHeaders {
		flags |= FlagPushPromiseEndHeaders
	}
	f.startWrite(FramePushPromise, flags, p.StreamID)
	if p.PadLength != 0 {
		f.writeByte(p.PadLength)
	}
	if !validStreamID(p.PromiseID) && !f.AllowIllegalWrites {
		return errStreamID
	}
	f.writeUint32(p.PromiseID)
	f.wbuf = append(f.wbuf, p.BlockFragment...)
	f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...)
	return f.endWrite()
}

// WriteRawFrame writes a raw frame. This can be used to write
// extension frames unknown to this package.
func (f *Framer) WriteRawFrame(t FrameType, flags Flags, streamID uint32, payload []byte) error {
	f.startWrite(t, flags, streamID)
	f.writeBytes(payload)
	return f.endWrite()
}

func readByte(p []byte) (remain []byte, b byte, err error) {
	if len(p) == 0 {
		return nil, 0, io.ErrUnexpectedEOF
	}
	return p[1:], p[0], nil
}

func readUint32(p []byte) (remain []byte, v uint32, err error) {
	if len(p) < 4 {
		return nil, 0, io.ErrUnexpectedEOF
	}
	return p[4:], binary.BigEndian.Uint32(p[:4]), nil
}

type streamEnder interface {
	StreamEnded() bool
}

type headersEnder interface {
	HeadersEnded() bool
}


================================================
FILE: vendor/github.com/bradfitz/http2/gotrack.go
================================================
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
// Licensed under the same terms as Go itself:
// https://code.google.com/p/go/source/browse/LICENSE

// Defensive debug-only utility to track that functions run on the
// goroutine that they're supposed to.

package http2

import (
	"bytes"
	"errors"
	"fmt"
	"os"
	"runtime"
	"strconv"
	"sync"
)

var DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"

type goroutineLock uint64

func newGoroutineLock() goroutineLock {
	if !DebugGoroutines {
		return 0
	}
	return goroutineLock(curGoroutineID())
}

func (g goroutineLock) check() {
	if !DebugGoroutines {
		return
	}
	if curGoroutineID() != uint64(g) {
		panic("running on the wrong goroutine")
	}
}

func (g goroutineLock) checkNotOn() {
	if !DebugGoroutines {
		return
	}
	if curGoroutineID() == uint64(g) {
		panic("running on the wrong goroutine")
	}
}

var goroutineSpace = []byte("goroutine ")

func curGoroutineID() uint64 {
	bp := littleBuf.Get().(*[]byte)
	defer littleBuf.Put(bp)
	b := *bp
	b = b[:runtime.Stack(b, false)]
	// Parse the 4707 out of "goroutine 4707 ["
	b = bytes.TrimPrefix(b, goroutineSpace)
	i := bytes.IndexByte(b, ' ')
	if i < 0 {
		panic(fmt.Sprintf("No space found in %q", b))
	}
	b = b[:i]
	n, err := parseUintBytes(b, 10, 64)
	if err != nil {
		panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", b, err))
	}
	return n
}

var littleBuf = sync.Pool{
	New: func() interface{} {
		buf := make([]byte, 64)
		return &buf
	},
}

// parseUintBytes is like strconv.ParseUint, but using a []byte.
func parseUintBytes(s []byte, base int, bitSize int) (n uint64, err error) {
	var cutoff, maxVal uint64

	if bitSize == 0 {
		bitSize = int(strconv.IntSize)
	}

	s0 := s
	switch {
	case len(s) < 1:
		err = strconv.ErrSyntax
		goto Error

	case 2 <= base && base <= 36:
		// valid base; nothing to do

	case base == 0:
		// Look for octal, hex prefix.
		switch {
		case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
			base = 16
			s = s[2:]
			if len(s) < 1 {
				err = strconv.ErrSyntax
				goto Error
			}
		case s[0] == '0':
			base = 8
		default:
			base = 10
		}

	default:
		err = errors.New("invalid base " + strconv.Itoa(base))
		goto Error
	}

	n = 0
	cutoff = cutoff64(base)
	maxVal = 1<<uint(bitSize) - 1

	for i := 0; i < len(s); i++ {
		var v byte
		d := s[i]
		switch {
		case '0' <= d && d <= '9':
			v = d - '0'
		case 'a' <= d && d <= 'z':
			v = d - 'a' + 10
		case 'A' <= d && d <= 'Z':
			v = d - 'A' + 10
		default:
			n = 0
			err = strconv.ErrSyntax
			goto Error
		}
		if int(v) >= base {
			n = 0
			err = strconv.ErrSyntax
			goto Error
		}

		if n >= cutoff {
			// n*base overflows
			n = 1<<64 - 1
			err = strconv.ErrRange
			goto Error
		}
		n *= uint64(base)

		n1 := n + uint64(v)
		if n1 < n || n1 > maxVal {
			// n+v overflows
			n = 1<<64 - 1
			err = strconv.ErrRange
			goto Error
		}
		n = n1
	}

	return n, nil

Error:
	return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
}

// Return the first number n such that n*base >= 1<<64.
func cutoff64(base int) uint64 {
	if base < 2 {
		return 0
	}
	return (1<<64-1)/uint64(base) + 1
}


================================================
FILE: vendor/github.com/bradfitz/http2/h2i/README.md
================================================
# h2i

**h2i** is an interactive HTTP/2 ("h2") console debugger. Miss the good ol'
days of telnetting to your HTTP/1.n servers? We're bringing you
back.

Features:
- send raw HTTP/2 frames
 - PING
 - SETTINGS
 - HEADERS
 - etc
- type in HTTP/1.n and have it auto-HPACK/frame-ify it for HTTP/2
- pretty print all received HTTP/2 frames from the peer (including HPACK decoding)
- tab completion of commands, options

Not yet features, but soon:
- unnecessary CONTINUATION frames on short boundaries, to test peer implementations 
- request bodies (DATA frames)
- send invalid frames for testing server implementations (supported by underlying Framer)

Later:
- act like a server

## Installation

```
$ go get github.com/bradfitz/http2/h2i
$ h2i <host>
```

## Demo

```
$ h2i
Usage: h2i <hostname>
  
  -insecure
        Whether to skip TLS cert validation
  -nextproto string
        Comma-separated list of NPN/ALPN protocol names to negotiate. (default "h2,h2-14")

$ h2i google.com
Connecting to google.com:443 ...
Connected to 74.125.224.41:443
Negotiated protocol "h2-14"
[FrameHeader SETTINGS len=18]
  [MAX_CONCURRENT_STREAMS = 100]
  [INITIAL_WINDOW_SIZE = 1048576]
  [MAX_FRAME_SIZE = 16384]
[FrameHeader WINDOW_UPDATE len=4]
  Window-Increment = 983041
  
h2i> PING h2iSayHI
[FrameHeader PING flags=ACK len=8]
  Data = "h2iSayHI"
h2i> headers
(as HTTP/1.1)> GET / HTTP/1.1
(as HTTP/1.1)> Host: ip.appspot.com
(as HTTP/1.1)> User-Agent: h2i/brad-n-blake
(as HTTP/1.1)>  
Opening Stream-ID 1:
 :authority = ip.appspot.com
 :method = GET
 :path = /
 :scheme = https
 user-agent = h2i/brad-n-blake
[FrameHeader HEADERS flags=END_HEADERS stream=1 len=77]
  :status = "200"
  alternate-protocol = "443:quic,p=1"
  content-length = "15"
  content-type = "text/html"
  date = "Fri, 01 May 2015 23:06:56 GMT"
  server = "Google Frontend"
[FrameHeader DATA flags=END_STREAM stream=1 len=15]
  "173.164.155.78\n"
[FrameHeader PING len=8]
  Data = "\x00\x00\x00\x00\x00\x00\x00\x00"
h2i> ping  
[FrameHeader PING flags=ACK len=8]  
  Data = "h2i_ping"  
h2i> ping  
[FrameHeader PING flags=ACK len=8]
  Data = "h2i_ping"
h2i> ping
[FrameHeader GOAWAY len=22]
  Last-Stream-ID = 1; Error-Code = PROTOCOL_ERROR (1)

ReadFrame: EOF
```

## Status

Quick few hour hack. So much yet to do. Feel free to file issues for
bugs or wishlist items, but [@bmizerany](https://github.com/bmizerany/)
and I aren't yet accepting pull requests until things settle down.



================================================
FILE: vendor/github.com/bradfitz/http2/h2i/h2i.go
================================================
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// See https://code.google.com/p/go/source/browse/CONTRIBUTORS
// Licensed under the same terms as Go itself:
// https://code.google.com/p/go/source/browse/LICENSE

/*
The h2i command is an interactive HTTP/2 console.

Usage:
  $ h2i [flags] <hostname>

Interactive commands in the console: (all parts case-insensitive)

  ping [data]
  settings ack
  settings FOO=n BAR=z
  headers      (open a new stream by typing HTTP/1.1)
*/
package main

import (
	"bufio"
	"bytes"
	"crypto/tls"
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"strings"

	"github.com/bradfitz/http2"
	"github.com/bradfitz/http2/hpack"
	"golang.org/x/crypto/ssh/terminal"
)

// Flags
var (
	flagNextProto = flag.String("nextproto", "h2,h2-14", "Comma-separated list of NPN/ALPN protocol names to negotiate.")
	flagInsecure  = flag.Bool("insecure", false, "Whether to skip TLS cert validation")
)

type command struct {
	run func(*h2i, []string) error // required

	// complete optionally specifies tokens (case-insensitive) which are
	// valid for this subcommand.
	complete func() []string
}

var commands = map[string]command{
	"ping": command{run: (*h2i).cmdPing},
	"settings": command{
		run: (*h2i).cmdSettings,
		complete: func() []string {
			return []string{
				"ACK",
				http2.SettingHeaderTableSize.String(),
				http2.SettingEnablePush.String(),
				http2.SettingMaxConcurrentStreams.String(),
				http2.SettingInitialWindowSize.String(),
				http2.SettingMaxFrameSize.String(),
				http2.SettingMaxHeaderListSize.String(),
			}
		},
	},
	"quit":    command{run: (*h2i).cmdQuit},
	"headers": command{run: (*h2i).cmdHeaders},
}

func usage() {
	fmt.Fprintf(os.Stderr, "Usage: h2i <hostname>\n\n")
	flag.PrintDefaults()
	os.Exit(1)
}

// withPort adds ":443" if another port isn't already present.
func withPort(host string) string {
	if _, _, err := net.SplitHostPort(host); err != nil {
		return net.JoinHostPort(host, "443")
	}
	return host
}

// h2i is the app's state.
type h2i struct {
	host   string
	tc     *tls.Conn
	framer *http2.Framer
	term   *terminal.Terminal

	// owned by the command loop:
	streamID uint32
	hbuf     bytes.Buffer
	henc     *hpack.Encoder

	// owned by the readFrames loop:
	peerSetting map[http2.SettingID]uint32
	hdec        *hpack.Decoder
}

func main() {
	flag.Usage = usage
	flag.Parse()
	if flag.NArg() != 1 {
		usage()
	}
	log.SetFlags(0)

	host := flag.Arg(0)
	app := &h2i{
		host:        host,
		peerSetting: make(map[http2.SettingID]uint32),
	}
	app.henc = hpack.NewEncoder(&app.hbuf)

	if err := app.Main(); err != nil {
		if app.term != nil {
			app.logf("%v\n", err)
		} else {
			fmt.Fprintf(os.Stderr, "%v\n", err)
		}
		os.Exit(1)
	}
	fmt.Fprintf(os.Stdout, "\n")
}

func (app *h2i) Main() error {
	cfg := &tls.Config{
		ServerName:         app.host,
		NextProtos:         strings.Split(*flagNextProto, ","),
		InsecureSkipVerify: *flagInsecure,
	}

	hostAndPort := withPort(app.host)
	log.Printf("Connecting to %s ...", hostAndPort)
	tc, err := tls.Dial("tcp", hostAndPort, cfg)
	if err != nil {
		return fmt.Errorf("Error dialing %s: %v", withPort(app.host), err)
	}
	log.Printf("Connected to %v", tc.RemoteAddr())
	defer tc.Close()

	if err := tc.Handshake(); err != nil {
		return fmt.Errorf("TLS handshake: %v", err)
	}
	if !*flagInsecure {
		if err := tc.VerifyHostname(app.host); err != nil {
			return fmt.Errorf("VerifyHostname: %v", err)
		}
	}
	state := tc.ConnectionState()
	log.Printf("Negotiated protocol %q", state.NegotiatedProtocol)
	if !state.NegotiatedProtocolIsMutual || state.NegotiatedProtocol == "" {
		return fmt.Errorf("Could not negotiate protocol mutually")
	}

	if _, err := io.WriteString(tc, http2.ClientPreface); err != nil {
		return err
	}

	app.framer = http2.NewFramer(tc, tc)

	oldState, err := terminal.MakeRaw(0)
	if err != nil {
		return err
	}
	defer terminal.Restore(0, oldState)

	var screen = struct {
		io.Reader
		io.Writer
	}{os.Stdin, os.Stdout}

	app.term = terminal.NewTerminal(screen, "h2i> ")
	lastWord := regexp.MustCompile(`.+\W(\w+)$`)
	app.term.AutoCompleteCallback = func(line string, pos int, key rune) (newLine string, newPos int, ok bool) {
		if key != '\t' {
			return
		}
		if pos != len(line) {
			// TODO: we're being lazy for now, only supporting tab completion at the end.
			return
		}
		// Auto-complete for the command itself.
		if !strings.Contains(line, " ") {
			var name string
			name, _, ok = lookupCommand(line)
			if !ok {
				return
			}
			return name, len(name), true
		}
		_, c, ok := lookupCommand(line[:strings.IndexByte(line, ' ')])
		if !ok || c.complete == nil {
			return
		}
		if strings.HasSuffix(line, " ") {
			app.logf("%s", strings.Join(c.complete(), " "))
			return line, pos, true
		}
		m := lastWord.FindStringSubmatch(line)
		if m == nil {
			return line, len(line), true
		}
		soFar := m[1]
		var match []string
		for _, cand := range c.complete() {
			if len(soFar) > len(cand) || !strings.EqualFold(cand[:len(soFar)], soFar) {
				continue
			}
			match = append(match, cand)
		}
		if len(match) == 0 {
			return
		}
		if len(match) > 1 {
			// TODO: auto-complete any common prefix
			app.logf("%s", strings.Join(match, " "))
			return line, pos, true
		}
		newLine = line[:len(line)-len(soFar)] + match[0]
		return newLine, len(newLine), true

	}

	errc := make(chan error, 2)
	go func() { errc <- app.readFrames() }()
	go func() { errc <- app.readConsole() }()
	return <-errc
}

func (app *h2i) logf(format string, args ...interface{}) {
	fmt.Fprintf(app.term, format+"\n", args...)
}

func (app *h2i) readConsole() error {
	for {
		line, err := app.term.ReadLine()
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return fmt.Errorf("terminal.ReadLine: %v", err)
		}
		f := strings.Fields(line)
		if len(f) == 0 {
			continue
		}
		cmd, args := f[0], f[1:]
		if _, c, ok := lookupCommand(cmd); ok {
			err = c.run(app, args)
		} else {
			app.logf("Unknown command %q", line)
		}
		if err == errExitApp {
			return nil
		}
		if err != nil {
			return err
		}
	}
}

func lookupCommand(prefix string) (name string, c command, ok bool) {
	prefix = strings.ToLower(prefix)
	if c, ok = commands[prefix]; ok {
		return prefix, c, ok
	}

	for full, candidate := range commands {
		if strings.HasPrefix(full, prefix) {
			if c.run != nil {
				return "", command{}, false // ambiguous
			}
			c = candidate
			name = full
		}
	}
	return name, c, c.run != nil
}

var errExitApp = errors.New("internal sentinel error value to quit the console reading loop")

func (a *h2i) cmdQuit(args []string) error {
	if len(args) > 0 
Download .txt
gitextract_yns78iqd/

├── .buildpacks
├── .gitignore
├── .travis.yml
├── Dockerfile
├── Godeps/
│   ├── Godeps.json
│   └── Readme
├── LICENSE
├── Procfile
├── README.md
├── app.json
├── config/
│   ├── config.go
│   └── default.conf.json
├── docker/
│   ├── build_gm.sh
│   ├── conf.json
│   └── meme.traineddata
├── goclean.sh
├── imageprocessor/
│   ├── compresslosslessly.go
│   ├── exifstripper.go
│   ├── imageorienter.go
│   ├── imageprocessor.go
│   ├── imagescaler.go
│   ├── ocr.go
│   ├── ocr_test.go
│   ├── processorcommand/
│   │   ├── gm.go
│   │   ├── jpegtran.go
│   │   ├── ocrcommands.go
│   │   ├── optipng.go
│   │   ├── runner.go
│   │   └── stripmetadata.go
│   └── thumbType/
│       └── thumbType.go
├── imagestore/
│   ├── factory.go
│   ├── gcsstore.go
│   ├── hash.go
│   ├── localstore.go
│   ├── memorystore.go
│   ├── namepathmapper.go
│   ├── s3store.go
│   ├── store.go
│   └── storeobject.go
├── main.go
├── server/
│   ├── authenticator.go
│   ├── authenticator_test.go
│   ├── server.go
│   ├── server_test.go
│   └── stats.go
├── uploadedfile/
│   ├── thumbfile.go
│   └── uploadedfile.go
└── vendor/
    ├── github.com/
    │   ├── PagerDuty/
    │   │   └── godspeed/
    │   │       ├── .gitignore
    │   │       ├── .travis.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── async.go
    │   │       ├── events.go
    │   │       ├── godspeed.go
    │   │       ├── service_checks.go
    │   │       ├── shared.go
    │   │       └── stats.go
    │   ├── bradfitz/
    │   │   └── http2/
    │   │       ├── .gitignore
    │   │       ├── AUTHORS
    │   │       ├── CONTRIBUTORS
    │   │       ├── Dockerfile
    │   │       ├── HACKING
    │   │       ├── LICENSE
    │   │       ├── Makefile
    │   │       ├── README
    │   │       ├── buffer.go
    │   │       ├── errors.go
    │   │       ├── flow.go
    │   │       ├── frame.go
    │   │       ├── gotrack.go
    │   │       ├── h2i/
    │   │       │   ├── README.md
    │   │       │   └── h2i.go
    │   │       ├── headermap.go
    │   │       ├── hpack/
    │   │       │   ├── encode.go
    │   │       │   ├── hpack.go
    │   │       │   ├── huffman.go
    │   │       │   └── tables.go
    │   │       ├── http2.go
    │   │       ├── pipe.go
    │   │       ├── server.go
    │   │       ├── transport.go
    │   │       ├── write.go
    │   │       └── writesched.go
    │   ├── golang/
    │   │   ├── glog/
    │   │   │   ├── LICENSE
    │   │   │   ├── README
    │   │   │   ├── glog.go
    │   │   │   └── glog_file.go
    │   │   └── protobuf/
    │   │       ├── LICENSE
    │   │       └── proto/
    │   │           ├── Makefile
    │   │           ├── clone.go
    │   │           ├── decode.go
    │   │           ├── encode.go
    │   │           ├── equal.go
    │   │           ├── extensions.go
    │   │           ├── lib.go
    │   │           ├── message_set.go
    │   │           ├── pointer_reflect.go
    │   │           ├── pointer_unsafe.go
    │   │           ├── properties.go
    │   │           ├── proto3_proto/
    │   │           │   ├── proto3.pb.go
    │   │           │   └── proto3.proto
    │   │           ├── text.go
    │   │           └── text_parser.go
    │   ├── gorilla/
    │   │   ├── context/
    │   │   │   ├── .travis.yml
    │   │   │   ├── LICENSE
    │   │   │   ├── README.md
    │   │   │   ├── context.go
    │   │   │   └── doc.go
    │   │   └── mux/
    │   │       ├── .travis.yml
    │   │       ├── LICENSE
    │   │       ├── README.md
    │   │       ├── doc.go
    │   │       ├── mux.go
    │   │       ├── regexp.go
    │   │       └── route.go
    │   ├── mitchellh/
    │   │   └── goamz/
    │   │       ├── LICENSE
    │   │       ├── aws/
    │   │       │   ├── attempt.go
    │   │       │   ├── aws.go
    │   │       │   └── client.go
    │   │       └── s3/
    │   │           ├── multi.go
    │   │           ├── s3.go
    │   │           ├── s3test/
    │   │           │   └── server.go
    │   │           └── sign.go
    │   ├── trustmaster/
    │   │   └── go-aspell/
    │   │       ├── README.md
    │   │       └── aspell.go
    │   └── vaughan0/
    │       └── go-ini/
    │           ├── LICENSE
    │           ├── README.md
    │           ├── ini.go
    │           └── test.ini
    ├── golang.org/
    │   └── x/
    │       ├── crypto/
    │       │   ├── LICENSE
    │       │   ├── PATENTS
    │       │   └── ssh/
    │       │       └── terminal/
    │       │           ├── terminal.go
    │       │           ├── util.go
    │       │           ├── util_bsd.go
    │       │           ├── util_linux.go
    │       │           └── util_windows.go
    │       ├── net/
    │       │   ├── LICENSE
    │       │   ├── PATENTS
    │       │   └── context/
    │       │       └── context.go
    │       └── oauth2/
    │           ├── .travis.yml
    │           ├── AUTHORS
    │           ├── CONTRIBUTING.md
    │           ├── CONTRIBUTORS
    │           ├── LICENSE
    │           ├── README.md
    │           ├── client_appengine.go
    │           ├── clientcredentials/
    │           │   └── clientcredentials.go
    │           ├── facebook/
    │           │   └── facebook.go
    │           ├── github/
    │           │   └── github.go
    │           ├── google/
    │           │   ├── appengine.go
    │           │   ├── appengine_hook.go
    │           │   ├── default.go
    │           │   ├── google.go
    │           │   └── sdk.go
    │           ├── internal/
    │           │   ├── oauth2.go
    │           │   ├── token.go
    │           │   └── transport.go
    │           ├── jws/
    │           │   └── jws.go
    │           ├── jwt/
    │           │   └── jwt.go
    │           ├── linkedin/
    │           │   └── linkedin.go
    │           ├── oauth2.go
    │           ├── odnoklassniki/
    │           │   └── odnoklassniki.go
    │           ├── paypal/
    │           │   └── paypal.go
    │           ├── token.go
    │           ├── transport.go
    │           └── vk/
    │               └── vk.go
    └── google.golang.org/
        ├── api/
        │   ├── LICENSE
        │   ├── bigquery/
        │   │   └── v2/
        │   │       ├── bigquery-api.json
        │   │       └── bigquery-gen.go
        │   ├── container/
        │   │   └── v1beta1/
        │   │       ├── container-api.json
        │   │       └── container-gen.go
        │   ├── googleapi/
        │   │   ├── googleapi.go
        │   │   ├── internal/
        │   │   │   └── uritemplates/
        │   │   │       ├── LICENSE
        │   │   │       ├── uritemplates.go
        │   │   │       └── utils.go
        │   │   ├── transport/
        │   │   │   └── apikey.go
        │   │   └── types.go
        │   ├── pubsub/
        │   │   └── v1beta2/
        │   │       ├── pubsub-api.json
        │   │       └── pubsub-gen.go
        │   └── storage/
        │       └── v1/
        │           ├── storage-api.json
        │           └── storage-gen.go
        ├── appengine/
        │   ├── .travis.yml
        │   ├── LICENSE
        │   ├── README.md
        │   ├── aetest/
        │   │   ├── doc.go
        │   │   ├── instance.go
        │   │   ├── instance_classic.go
        │   │   ├── instance_vm.go
        │   │   └── user.go
        │   ├── appengine.go
        │   ├── appengine_vm.go
        │   ├── blobstore/
        │   │   ├── blobstore.go
        │   │   └── read.go
        │   ├── capability/
        │   │   └── capability.go
        │   ├── channel/
        │   │   └── channel.go
        │   ├── cloudsql/
        │   │   ├── cloudsql.go
        │   │   ├── cloudsql_classic.go
        │   │   └── cloudsql_vm.go
        │   ├── cmd/
        │   │   ├── aebundler/
        │   │   │   └── aebundler.go
        │   │   └── aedeploy/
        │   │       └── aedeploy.go
        │   ├── datastore/
        │   │   ├── datastore.go
        │   │   ├── doc.go
        │   │   ├── key.go
        │   │   ├── load.go
        │   │   ├── metadata.go
        │   │   ├── prop.go
        │   │   ├── query.go
        │   │   ├── save.go
        │   │   └── transaction.go
        │   ├── delay/
        │   │   └── delay.go
        │   ├── demos/
        │   │   ├── guestbook/
        │   │   │   ├── app.yaml
        │   │   │   ├── guestbook.go
        │   │   │   ├── index.yaml
        │   │   │   └── templates/
        │   │   │       └── guestbook.html
        │   │   └── helloworld/
        │   │       ├── app.yaml
        │   │       └── helloworld.go
        │   ├── errors.go
        │   ├── file/
        │   │   └── file.go
        │   ├── identity.go
        │   ├── image/
        │   │   └── image.go
        │   ├── internal/
        │   │   ├── aetesting/
        │   │   │   └── fake.go
        │   │   ├── api.go
        │   │   ├── api_classic.go
        │   │   ├── api_common.go
        │   │   ├── app_id.go
        │   │   ├── app_identity/
        │   │   │   ├── app_identity_service.pb.go
        │   │   │   └── app_identity_service.proto
        │   │   ├── base/
        │   │   │   ├── api_base.pb.go
        │   │   │   └── api_base.proto
        │   │   ├── blobstore/
        │   │   │   ├── blobstore_service.pb.go
        │   │   │   └── blobstore_service.proto
        │   │   ├── capability/
        │   │   │   ├── capability_service.pb.go
        │   │   │   └── capability_service.proto
        │   │   ├── channel/
        │   │   │   ├── channel_service.pb.go
        │   │   │   └── channel_service.proto
        │   │   ├── datastore/
        │   │   │   ├── datastore_v3.pb.go
        │   │   │   └── datastore_v3.proto
        │   │   ├── identity.go
        │   │   ├── identity_classic.go
        │   │   ├── identity_vm.go
        │   │   ├── image/
        │   │   │   ├── images_service.pb.go
        │   │   │   └── images_service.proto
        │   │   ├── internal.go
        │   │   ├── log/
        │   │   │   ├── log_service.pb.go
        │   │   │   └── log_service.proto
        │   │   ├── mail/
        │   │   │   ├── mail_service.pb.go
        │   │   │   └── mail_service.proto
        │   │   ├── memcache/
        │   │   │   ├── memcache_service.pb.go
        │   │   │   └── memcache_service.proto
        │   │   ├── metadata.go
        │   │   ├── modules/
        │   │   │   ├── modules_service.pb.go
        │   │   │   └── modules_service.proto
        │   │   ├── net.go
        │   │   ├── regen.sh
        │   │   ├── remote_api/
        │   │   │   ├── remote_api.pb.go
        │   │   │   └── remote_api.proto
        │   │   ├── search/
        │   │   │   ├── search.pb.go
        │   │   │   └── search.proto
        │   │   ├── socket/
        │   │   │   ├── socket_service.pb.go
        │   │   │   └── socket_service.proto
        │   │   ├── system/
        │   │   │   ├── system_service.pb.go
        │   │   │   └── system_service.proto
        │   │   ├── taskqueue/
        │   │   │   ├── taskqueue_service.pb.go
        │   │   │   └── taskqueue_service.proto
        │   │   ├── transaction.go
        │   │   ├── urlfetch/
        │   │   │   ├── urlfetch_service.pb.go
        │   │   │   └── urlfetch_service.proto
        │   │   ├── user/
        │   │   │   ├── user_service.pb.go
        │   │   │   └── user_service.proto
        │   │   └── xmpp/
        │   │       ├── xmpp_service.pb.go
        │   │       └── xmpp_service.proto
        │   ├── log/
        │   │   ├── api.go
        │   │   └── log.go
        │   ├── mail/
        │   │   └── mail.go
        │   ├── memcache/
        │   │   └── memcache.go
        │   ├── module/
        │   │   └── module.go
        │   ├── namespace.go
        │   ├── remote_api/
        │   │   ├── client.go
        │   │   └── remote_api.go
        │   ├── runtime/
        │   │   └── runtime.go
        │   ├── search/
        │   │   ├── doc.go
        │   │   ├── field.go
        │   │   ├── search.go
        │   │   └── struct.go
        │   ├── socket/
        │   │   ├── doc.go
        │   │   ├── socket_classic.go
        │   │   └── socket_vm.go
        │   ├── taskqueue/
        │   │   └── taskqueue.go
        │   ├── timeout.go
        │   ├── urlfetch/
        │   │   └── urlfetch.go
        │   ├── user/
        │   │   ├── oauth.go
        │   │   ├── user.go
        │   │   ├── user_classic.go
        │   │   └── user_vm.go
        │   └── xmpp/
        │       └── xmpp.go
        ├── cloud/
        │   ├── .travis.yml
        │   ├── AUTHORS
        │   ├── CONTRIBUTING.md
        │   ├── CONTRIBUTORS
        │   ├── LICENSE
        │   ├── README.md
        │   ├── bigquery/
        │   │   ├── bigquery.go
        │   │   ├── copy_op.go
        │   │   ├── doc.go
        │   │   ├── error.go
        │   │   ├── extract_op.go
        │   │   ├── gcs.go
        │   │   ├── iterator.go
        │   │   ├── job.go
        │   │   ├── load_op.go
        │   │   ├── query.go
        │   │   ├── query_op.go
        │   │   ├── read_op.go
        │   │   ├── schema.go
        │   │   ├── service.go
        │   │   ├── table.go
        │   │   └── value.go
        │   ├── bigtable/
        │   │   ├── admin.go
        │   │   ├── bigtable.go
        │   │   ├── bttest/
        │   │   │   └── inmem.go
        │   │   ├── cmd/
        │   │   │   └── cbt/
        │   │   │       ├── cbt.go
        │   │   │       └── cbtdoc.go
        │   │   ├── doc.go
        │   │   ├── filter.go
        │   │   ├── internal/
        │   │   │   ├── cluster_data_proto/
        │   │   │   │   ├── bigtable_cluster_data.pb.go
        │   │   │   │   └── bigtable_cluster_data.proto
        │   │   │   ├── cluster_service_proto/
        │   │   │   │   ├── bigtable_cluster_service.pb.go
        │   │   │   │   ├── bigtable_cluster_service.proto
        │   │   │   │   ├── bigtable_cluster_service_messages.pb.go
        │   │   │   │   └── bigtable_cluster_service_messages.proto
        │   │   │   ├── data_proto/
        │   │   │   │   ├── bigtable_data.pb.go
        │   │   │   │   └── bigtable_data.proto
        │   │   │   ├── empty/
        │   │   │   │   ├── empty.pb.go
        │   │   │   │   └── empty.proto
        │   │   │   ├── regen.sh
        │   │   │   ├── service_proto/
        │   │   │   │   ├── bigtable_service.pb.go
        │   │   │   │   ├── bigtable_service.proto
        │   │   │   │   ├── bigtable_service_messages.pb.go
        │   │   │   │   └── bigtable_service_messages.proto
        │   │   │   ├── table_data_proto/
        │   │   │   │   ├── bigtable_table_data.pb.go
        │   │   │   │   └── bigtable_table_data.proto
        │   │   │   └── table_service_proto/
        │   │   │       ├── bigtable_table_service.pb.go
        │   │   │       ├── bigtable_table_service.proto
        │   │   │       ├── bigtable_table_service_messages.pb.go
        │   │   │       └── bigtable_table_service_messages.proto
        │   │   └── sample/
        │   │       └── search.go
        │   ├── cloud.go
        │   ├── compute/
        │   │   └── metadata/
        │   │       └── metadata.go
        │   ├── container/
        │   │   └── container.go
        │   ├── datastore/
        │   │   ├── datastore.go
        │   │   ├── errors.go
        │   │   ├── key.go
        │   │   ├── load.go
        │   │   ├── prop.go
        │   │   ├── query.go
        │   │   ├── save.go
        │   │   ├── time.go
        │   │   └── transaction.go
        │   ├── examples/
        │   │   ├── bigquery/
        │   │   │   ├── concat_table/
        │   │   │   │   └── main.go
        │   │   │   ├── load/
        │   │   │   │   └── main.go
        │   │   │   ├── query/
        │   │   │   │   └── main.go
        │   │   │   └── read/
        │   │   │       └── main.go
        │   │   ├── pubsub/
        │   │   │   └── cmdline/
        │   │   │       └── main.go
        │   │   └── storage/
        │   │       ├── appengine/
        │   │       │   ├── app.go
        │   │       │   └── app.yaml
        │   │       └── appenginevm/
        │   │           ├── app.go
        │   │           └── app.yaml
        │   ├── internal/
        │   │   ├── cloud.go
        │   │   ├── datastore/
        │   │   │   ├── datastore_v1.pb.go
        │   │   │   └── datastore_v1.proto
        │   │   └── testutil/
        │   │       └── context.go
        │   ├── key.json.enc
        │   ├── option.go
        │   ├── pubsub/
        │   │   └── pubsub.go
        │   └── storage/
        │       ├── acl.go
        │       ├── storage.go
        │       └── types.go
        └── grpc/
            ├── .travis.yml
            ├── CONTRIBUTING.md
            ├── LICENSE
            ├── PATENTS
            ├── README.md
            ├── benchmark/
            │   ├── benchmark.go
            │   ├── client/
            │   │   └── main.go
            │   ├── grpc_testing/
            │   │   ├── test.pb.go
            │   │   └── test.proto
            │   ├── server/
            │   │   └── main.go
            │   └── stats/
            │       ├── counter.go
            │       ├── histogram.go
            │       ├── stats.go
            │       ├── timeseries.go
            │       ├── tracker.go
            │       └── util.go
            ├── call.go
            ├── clientconn.go
            ├── codegen.sh
            ├── codes/
            │   ├── code_string.go
            │   └── codes.go
            ├── credentials/
            │   └── credentials.go
            ├── doc.go
            ├── examples/
            │   └── route_guide/
            │       ├── README.md
            │       ├── client/
            │       │   └── client.go
            │       ├── proto/
            │       │   ├── route_guide.pb.go
            │       │   └── route_guide.proto
            │       └── server/
            │           └── server.go
            ├── grpc-auth-support.md
            ├── grpclog/
            │   └── logger.go
            ├── interop/
            │   ├── client/
            │   │   └── client.go
            │   ├── grpc_testing/
            │   │   ├── test.pb.go
            │   │   └── test.proto
            │   └── server/
            │       └── server.go
            ├── metadata/
            │   └── metadata.go
            ├── rpc_util.go
            ├── server.go
            ├── stream.go
            ├── test/
            │   ├── codec_perf/
            │   │   ├── perf.pb.go
            │   │   └── perf.proto
            │   └── grpc_testing/
            │       ├── test.pb.go
            │       └── test.proto
            └── transport/
                ├── control.go
                ├── http2_client.go
                ├── http2_server.go
                ├── http_util.go
                └── transport.go
Download .txt
Showing preview only (758K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (8322 symbols across 288 files)

FILE: config/config.go
  type Configuration (line 9) | type Configuration struct
  function NewConfiguration (line 19) | func NewConfiguration(path string) *Configuration {

FILE: imageprocessor/compresslosslessly.go
  type CompressLosslessly (line 10) | type CompressLosslessly struct
    method Process (line 12) | func (this *CompressLosslessly) Process(image *uploadedfile.UploadedFi...
    method String (line 28) | func (this *CompressLosslessly) String() string {
    method compressPng (line 32) | func (this *CompressLosslessly) compressPng(image *uploadedfile.Upload...
    method compressJpeg (line 43) | func (this *CompressLosslessly) compressJpeg(image *uploadedfile.Uploa...

FILE: imageprocessor/exifstripper.go
  type ExifStripper (line 8) | type ExifStripper struct
    method Process (line 10) | func (this *ExifStripper) Process(image *uploadedfile.UploadedFile) er...
    method String (line 23) | func (this *ExifStripper) String() string {

FILE: imageprocessor/imageorienter.go
  type ImageOrienter (line 8) | type ImageOrienter struct
    method Process (line 10) | func (this *ImageOrienter) Process(image *uploadedfile.UploadedFile) e...
    method String (line 21) | func (this *ImageOrienter) String() string {

FILE: imageprocessor/imageprocessor.go
  type ProcessType (line 11) | type ProcessType interface
  type multiProcessType (line 16) | type multiProcessType
    method Process (line 18) | func (this multiProcessType) Process(image *uploadedfile.UploadedFile)...
    method String (line 29) | func (this multiProcessType) String() string {
  type asyncProcessType (line 37) | type asyncProcessType
    method Process (line 39) | func (this asyncProcessType) Process(image *uploadedfile.UploadedFile)...
    method String (line 65) | func (this asyncProcessType) String() string {
  type ImageProcessor (line 73) | type ImageProcessor struct
    method Run (line 77) | func (this *ImageProcessor) Run(image *uploadedfile.UploadedFile) error {
  type ImageProcessorStrategy (line 81) | type ImageProcessorStrategy

FILE: imageprocessor/imagescaler.go
  type ImageScaler (line 10) | type ImageScaler struct
    method Process (line 14) | func (this *ImageScaler) Process(image *uploadedfile.UploadedFile) err...
    method String (line 27) | func (this *ImageScaler) String() string {
    method scalePng (line 31) | func (this *ImageScaler) scalePng(image *uploadedfile.UploadedFile) er...
    method scaleJpeg (line 42) | func (this *ImageScaler) scaleJpeg(image *uploadedfile.UploadedFile) e...
    method scaleGif (line 94) | func (this *ImageScaler) scaleGif(image *uploadedfile.UploadedFile) er...

FILE: imageprocessor/ocr.go
  type OCRRunner (line 10) | type OCRRunner struct
    method Process (line 14) | func (this *OCRRunner) Process(image *uploadedfile.UploadedFile) error {
    method String (line 26) | func (this *OCRRunner) String() string {

FILE: imageprocessor/ocr_test.go
  function TestStandardOCR (line 13) | func TestStandardOCR(t *testing.T) {
  function getUploadedFileObject (line 28) | func getUploadedFileObject() (*uploadedfile.UploadedFile, error) {
  function copyTestImage (line 42) | func copyTestImage(filename string) (string, error) {

FILE: imageprocessor/processorcommand/gm.go
  constant GM_COMMAND (line 9) | GM_COMMAND = "gm"
  function ConvertToJpeg (line 11) | func ConvertToJpeg(filename string) (string, error) {
  function FixOrientation (line 29) | func FixOrientation(filename string) (string, error) {
  function Quality (line 47) | func Quality(filename string, quality int) (string, error) {
  function ResizePercent (line 68) | func ResizePercent(filename string, percent int) (string, error) {
  function SquareThumb (line 87) | func SquareThumb(filename, name string, size int, quality int, format th...
  function Thumb (line 122) | func Thumb(filename, name string, width, height int, quality int, format...
  function CircleThumb (line 151) | func CircleThumb(filename, name string, width int, quality int, format t...
  function CustomThumb (line 191) | func CustomThumb(filename, name string, width, height int, cropGravity s...
  function Full (line 228) | func Full(filename string, name string, quality int, format thumbType.Th...

FILE: imageprocessor/processorcommand/jpegtran.go
  function Jpegtran (line 7) | func Jpegtran(filename string) (string, error) {

FILE: imageprocessor/processorcommand/ocrcommands.go
  type OCRResult (line 14) | type OCRResult struct
    method removeNonWords (line 26) | func (this *OCRResult) removeNonWords() {
    method wordCount (line 60) | func (this *OCRResult) wordCount(blob string) int {
  function newOCRResult (line 19) | func newOCRResult(ocrType string, result string) *OCRResult {
  type MultiOCRCommand (line 75) | type MultiOCRCommand
    method Run (line 77) | func (this MultiOCRCommand) Run(image string) (*OCRResult, error) {
  type OCRCommand (line 115) | type OCRCommand interface
  type MemeOCR (line 119) | type MemeOCR struct
    method Run (line 129) | func (this *MemeOCR) Run(image string) (*OCRResult, error) {
  function NewMemeOCR (line 123) | func NewMemeOCR() *MemeOCR {
  type StandardOCR (line 158) | type StandardOCR struct
    method Run (line 168) | func (this *StandardOCR) Run(image string) (*OCRResult, error) {
  function NewStandardOCR (line 162) | func NewStandardOCR() *StandardOCR {

FILE: imageprocessor/processorcommand/optipng.go
  function Optipng (line 7) | func Optipng(filename string) (string, error) {

FILE: imageprocessor/processorcommand/runner.go
  function runProcessorCommand (line 11) | func runProcessorCommand(command string, args []string) error {
  function killCmd (line 40) | func killCmd(cmd *exec.Cmd) {

FILE: imageprocessor/processorcommand/stripmetadata.go
  function StripMetadata (line 3) | func StripMetadata(filename string) error {

FILE: imageprocessor/thumbType/thumbType.go
  type ThumbType (line 3) | type ThumbType
    method ToString (line 13) | func (this ThumbType) ToString() string {
  constant UNKNOWN (line 6) | UNKNOWN ThumbType = iota
  constant JPG (line 7) | JPG
  constant PNG (line 8) | PNG
  constant GIF (line 9) | GIF
  constant WEBP (line 10) | WEBP
  function FromMime (line 28) | func FromMime(mime string) ThumbType {
  function FromString (line 43) | func FromString(format string) ThumbType {

FILE: imagestore/factory.go
  type Factory (line 17) | type Factory struct
    method NewImageStores (line 25) | func (this *Factory) NewImageStores() ImageStore {
    method NewS3ImageStore (line 56) | func (this *Factory) NewS3ImageStore(conf map[string]string) ImageStore {
    method NewGCSImageStore (line 75) | func (this *Factory) NewGCSImageStore(conf map[string]string) ImageSto...
    method NewLocalImageStore (line 101) | func (this *Factory) NewLocalImageStore(conf map[string]string) ImageS...
    method NewStoreObject (line 106) | func (this *Factory) NewStoreObject(id string, mime string, size strin...
    method NewHashGenerator (line 114) | func (this *Factory) NewHashGenerator(store ImageStore) *HashGenerator {
  function NewFactory (line 21) | func NewFactory(conf *config.Configuration) *Factory {

FILE: imagestore/gcsstore.go
  type GCSImageStore (line 13) | type GCSImageStore struct
    method Exists (line 29) | func (this *GCSImageStore) Exists(obj *StoreObject) (bool, error) {
    method Save (line 37) | func (this *GCSImageStore) Save(src string, obj *StoreObject) (*StoreO...
    method Get (line 65) | func (this *GCSImageStore) Get(obj *StoreObject) (io.ReadCloser, error) {
    method String (line 75) | func (this *GCSImageStore) String() string {
    method toPath (line 79) | func (this *GCSImageStore) toPath(obj *StoreObject) string {
  function NewGCSImageStore (line 20) | func NewGCSImageStore(ctx context.Context, bucket string, root string, m...

FILE: imagestore/hash.go
  type HashGenerator (line 9) | type HashGenerator struct
    method init (line 15) | func (this *HashGenerator) init() {
    method Get (line 75) | func (this *HashGenerator) Get() string {

FILE: imagestore/localstore.go
  type LocalImageStore (line 10) | type LocalImageStore struct
    method Exists (line 22) | func (this *LocalImageStore) Exists(obj *StoreObject) (bool, error) {
    method Save (line 30) | func (this *LocalImageStore) Save(src string, obj *StoreObject) (*Stor...
    method Get (line 55) | func (this *LocalImageStore) Get(obj *StoreObject) (io.ReadCloser, err...
    method String (line 64) | func (this *LocalImageStore) String() string {
    method createParent (line 68) | func (this *LocalImageStore) createParent(obj *StoreObject) {
    method toPath (line 76) | func (this *LocalImageStore) toPath(obj *StoreObject) string {
  function NewLocalImageStore (line 15) | func NewLocalImageStore(root string, mapper *NamePathMapper) *LocalImage...

FILE: imagestore/memorystore.go
  type InMemoryImageStore (line 12) | type InMemoryImageStore struct
    method Exists (line 24) | func (this *InMemoryImageStore) Exists(obj *StoreObject) (bool, error) {
    method Save (line 34) | func (this *InMemoryImageStore) Save(src string, obj *StoreObject) (*S...
    method Get (line 53) | func (this *InMemoryImageStore) Get(obj *StoreObject) (io.ReadCloser, ...
    method String (line 67) | func (this *InMemoryImageStore) String() string {
  function NewInMemoryImageStore (line 17) | func NewInMemoryImageStore() *InMemoryImageStore {

FILE: imagestore/namepathmapper.go
  type NamePathMapper (line 8) | type NamePathMapper struct
    method mapToPath (line 25) | func (this *NamePathMapper) mapToPath(obj *StoreObject) string {
  function NewNamePathMapper (line 13) | func NewNamePathMapper(expr string, mapping string) *NamePathMapper {

FILE: imagestore/s3store.go
  type S3ImageStore (line 10) | type S3ImageStore struct
    method Exists (line 26) | func (this *S3ImageStore) Exists(obj *StoreObject) (bool, error) {
    method Save (line 36) | func (this *S3ImageStore) Save(src string, obj *StoreObject) (*StoreOb...
    method Get (line 59) | func (this *S3ImageStore) Get(obj *StoreObject) (io.ReadCloser, error) {
    method String (line 69) | func (this *S3ImageStore) String() string {
    method toPath (line 73) | func (this *S3ImageStore) toPath(obj *StoreObject) string {
  function NewS3ImageStore (line 17) | func NewS3ImageStore(bucket string, root string, client *s3.S3, mapper *...

FILE: imagestore/store.go
  type ImageStore (line 8) | type ImageStore interface
  type MultiImageStore (line 15) | type MultiImageStore
    method Save (line 17) | func (this MultiImageStore) Save(src string, obj *StoreObject) (*Store...
    method Exists (line 43) | func (this MultiImageStore) Exists(obj *StoreObject) (bool, error) {
    method Get (line 74) | func (this MultiImageStore) Get(obj *StoreObject) (io.ReadCloser, erro...
    method String (line 108) | func (this MultiImageStore) String() string {

FILE: imagestore/storeobject.go
  type StorableObject (line 3) | type StorableObject interface
  type StoreObject (line 7) | type StoreObject struct
    method Store (line 14) | func (this *StoreObject) Store(s StorableObject, store ImageStore) err...

FILE: main.go
  function main (line 14) | func main() {

FILE: server/authenticator.go
  type AuthenticatedUser (line 22) | type AuthenticatedUser struct
  type Authenticator (line 28) | type Authenticator interface
  type PassthroughAuthenticator (line 32) | type PassthroughAuthenticator struct
    method GetUser (line 34) | func (auth *PassthroughAuthenticator) GetUser(req *http.Request) (*Aut...
  type HMACAuthenticator (line 38) | type HMACAuthenticator struct
    method SetTime (line 44) | func (auth *HMACAuthenticator) SetTime(t time.Time) {
    method GetUser (line 55) | func (auth *HMACAuthenticator) GetUser(req *http.Request) (*Authentica...
  function NewHMACAuthenticatorSHA256 (line 48) | func NewHMACAuthenticatorSHA256(key []byte) *HMACAuthenticator {

FILE: server/authenticator_test.go
  function TestPassthroughAuthenticatorAlwaysReturnsNilUser (line 13) | func TestPassthroughAuthenticatorAlwaysReturnsNilUser(t *testing.T) {
  function TestHMACAuthenticatorOnValidRequest (line 26) | func TestHMACAuthenticatorOnValidRequest(t *testing.T) {
  function TestHMACAuthenticatorOnEmptyHeader (line 53) | func TestHMACAuthenticatorOnEmptyHeader(t *testing.T) {
  function TestHMACAuthenticatorOnInvalidRequest (line 68) | func TestHMACAuthenticatorOnInvalidRequest(t *testing.T) {
  function TestHMACAuthenticatorOnExpiredGrant (line 96) | func TestHMACAuthenticatorOnExpiredGrant(t *testing.T) {

FILE: server/server.go
  type Server (line 25) | type Server struct
    method uploadFile (line 108) | func (s *Server) uploadFile(uploadFile io.Reader, fileName string, thu...
    method Configure (line 212) | func (s *Server) Configure(muxer *http.ServeMux) {
    method buildThumbResponse (line 522) | func (s *Server) buildThumbResponse(upload *uploadedfile.UploadedFile)...
    method download (line 541) | func (s *Server) download(url string) (io.ReadCloser, error) {
  type ServerResponse (line 35) | type ServerResponse struct
    method Write (line 42) | func (resp *ServerResponse) Write(w http.ResponseWriter, s RuntimeStat...
    method json (line 57) | func (resp *ServerResponse) json() ([]byte, error) {
  type ImageResponse (line 66) | type ImageResponse struct
  type OcrResponse (line 79) | type OcrResponse struct
  type UserError (line 84) | type UserError struct
  function NewServer (line 89) | func NewServer(c *config.Configuration, strategy imageprocessor.ImagePro...
  function NewAuthenticatedServer (line 99) | func NewAuthenticatedServer(c *config.Configuration, strategy imageproce...
  type fileExtractor (line 210) | type fileExtractor
  function parseThumbs (line 570) | func parseThumbs(r *http.Request) ([]*uploadedfile.ThumbFile, error) {
  function saveToTmp (line 622) | func saveToTmp(upload io.Reader) (string, error) {

FILE: server/server_test.go
  function TestRequestingTheFrontPageGetsSomeHTML (line 22) | func TestRequestingTheFrontPageGetsSomeHTML(t *testing.T) {
  function TestPostingBase64FilePutsTheFileInStorageAndReturnsJSON (line 66) | func TestPostingBase64FilePutsTheFileInStorageAndReturnsJSON(t *testing....
  function TestAuthentication (line 161) | func TestAuthentication(t *testing.T) {
  function TestGetFullWebpThumb (line 246) | func TestGetFullWebpThumb(t *testing.T) {
  function TestGetSizedWebpThumb (line 339) | func TestGetSizedWebpThumb(t *testing.T) {
  function TestTooLarge (line 444) | func TestTooLarge(t *testing.T) {
  function TestTooSmall (line 502) | func TestTooSmall(t *testing.T) {
  function TestGetTallThumb (line 560) | func TestGetTallThumb(t *testing.T) {

FILE: server/stats.go
  type RuntimeStats (line 11) | type RuntimeStats interface
  type DiscardStats (line 21) | type DiscardStats struct
    method LogStartup (line 23) | func (d *DiscardStats) LogStartup()                                    {}
    method Request (line 24) | func (d *DiscardStats) Request(url string)                             {}
    method ResponseTime (line 25) | func (d *DiscardStats) ResponseTime(elapsed time.Duration, url string) {}
    method Thumbnail (line 26) | func (d *DiscardStats) Thumbnail(name string)                          {}
    method Upload (line 27) | func (d *DiscardStats) Upload(source string)                           {}
    method Error (line 28) | func (d *DiscardStats) Error(code int)                                 {}
  type DatadogStats (line 30) | type DatadogStats struct
    method LogStartup (line 60) | func (d *DatadogStats) LogStartup() {
    method Request (line 64) | func (d *DatadogStats) Request(url string) {
    method ResponseTime (line 70) | func (d *DatadogStats) ResponseTime(elapsed time.Duration, url string) {
    method Thumbnail (line 77) | func (d *DatadogStats) Thumbnail(name string) {
    method Upload (line 83) | func (d *DatadogStats) Upload(source string) {
    method Error (line 89) | func (d *DatadogStats) Error(code int) {
  function NewDatadogStats (line 34) | func NewDatadogStats(datadogHost string) (*DatadogStats, error) {

FILE: uploadedfile/thumbfile.go
  type ThumbFile (line 20) | type ThumbFile struct
    method GetNoStore (line 66) | func (this *ThumbFile) GetNoStore() bool {
    method SetPath (line 70) | func (this *ThumbFile) SetPath(path string) error {
    method GetPath (line 80) | func (this *ThumbFile) GetPath() string {
    method GetOutputFormat (line 84) | func (this *ThumbFile) GetOutputFormat(original *UploadedFile) thumbTy...
    method ComputeWidth (line 92) | func (this *ThumbFile) ComputeWidth(original *UploadedFile) int {
    method ComputeHeight (line 107) | func (this *ThumbFile) ComputeHeight(original *UploadedFile) int {
    method ComputeCrop (line 122) | func (this *ThumbFile) ComputeCrop(original *UploadedFile) (int, int, ...
    method Process (line 152) | func (this *ThumbFile) Process(original *UploadedFile) error {
    method String (line 167) | func (this *ThumbFile) String() string {
    method processSquare (line 171) | func (this *ThumbFile) processSquare(original *UploadedFile) error {
    method processCircle (line 191) | func (this *ThumbFile) processCircle(original *UploadedFile) error {
    method processThumb (line 214) | func (this *ThumbFile) processThumb(original *UploadedFile) error {
    method processCustom (line 240) | func (this *ThumbFile) processCustom(original *UploadedFile) error {
    method processFull (line 277) | func (this *ThumbFile) processFull(original *UploadedFile) error {
  function NewThumbFile (line 40) | func NewThumbFile(width, maxWidth, height, maxHeight int, name, shape, p...

FILE: uploadedfile/uploadedfile.go
  type UploadedFile (line 13) | type UploadedFile struct
    method GetFilename (line 59) | func (this *UploadedFile) GetFilename() string {
    method SetFilename (line 63) | func (this *UploadedFile) SetFilename(filename string) {
    method GetHash (line 67) | func (this *UploadedFile) GetHash() string {
    method SetHash (line 71) | func (this *UploadedFile) SetHash(hash string) {
    method GetOCRText (line 75) | func (this *UploadedFile) GetOCRText() string {
    method SetOCRText (line 79) | func (this *UploadedFile) SetOCRText(text string) {
    method SetPath (line 83) | func (this *UploadedFile) SetPath(path string) {
    method GetPath (line 90) | func (this *UploadedFile) GetPath() string {
    method GetMime (line 94) | func (this *UploadedFile) GetMime() string {
    method SetMime (line 98) | func (this *UploadedFile) SetMime(mime string) {
    method SetThumbs (line 102) | func (this *UploadedFile) SetThumbs(thumbs []*ThumbFile) {
    method GetThumbs (line 106) | func (this *UploadedFile) GetThumbs() []*ThumbFile {
    method FileSize (line 110) | func (this *UploadedFile) FileSize() (int64, error) {
    method Clean (line 126) | func (this *UploadedFile) Clean() {
    method Dimensions (line 134) | func (this *UploadedFile) Dimensions() (int, int, error) {
    method IsJpeg (line 159) | func (this *UploadedFile) IsJpeg() bool {
    method IsPng (line 163) | func (this *UploadedFile) IsPng() bool {
    method IsGif (line 167) | func (this *UploadedFile) IsGif() bool {
  function NewUploadedFile (line 29) | func NewUploadedFile(filename, path string, thumbs []*ThumbFile) (*Uploa...

FILE: vendor/github.com/PagerDuty/godspeed/async.go
  type AsyncGodspeed (line 12) | type AsyncGodspeed struct
    method AddTag (line 49) | func (a *AsyncGodspeed) AddTag(tag string) []string {
    method AddTags (line 54) | func (a *AsyncGodspeed) AddTags(tags []string) []string {
    method SetNamespace (line 59) | func (a *AsyncGodspeed) SetNamespace(ns string) {
    method Event (line 66) | func (a *AsyncGodspeed) Event(title, body string, keys map[string]stri...
    method Send (line 74) | func (a *AsyncGodspeed) Send(stat, kind string, delta, sampleRate floa...
    method ServiceCheck (line 82) | func (a *AsyncGodspeed) ServiceCheck(name string, status int, fields m...
    method Count (line 93) | func (a *AsyncGodspeed) Count(stat string, count float64, tags []strin...
    method Incr (line 101) | func (a *AsyncGodspeed) Incr(stat string, tags []string, y *sync.WaitG...
    method Decr (line 112) | func (a *AsyncGodspeed) Decr(stat string, tags []string, y *sync.WaitG...
    method Gauge (line 120) | func (a *AsyncGodspeed) Gauge(stat string, value float64, tags []strin...
    method Histogram (line 128) | func (a *AsyncGodspeed) Histogram(stat string, value float64, tags []s...
    method Timing (line 136) | func (a *AsyncGodspeed) Timing(stat string, value float64, tags []stri...
    method Set (line 143) | func (a *AsyncGodspeed) Set(stat string, value float64, tags []string,...
  function NewAsync (line 27) | func NewAsync(host string, port int, autoTruncate bool) (a *AsyncGodspee...
  function NewDefaultAsync (line 43) | func NewDefaultAsync() (a *AsyncGodspeed, err error) {

FILE: vendor/github.com/PagerDuty/godspeed/events.go
  function escapeEvent (line 16) | func escapeEvent(s string) string {
  function removePipes (line 20) | func removePipes(s string) string {
  method Event (line 28) | func (g *Godspeed) Event(title, text string, fields map[string]string, t...

FILE: vendor/github.com/PagerDuty/godspeed/godspeed.go
  constant DefaultHost (line 25) | DefaultHost = "127.0.0.1"
  constant DefaultPort (line 28) | DefaultPort = 8125
  constant MaxBytes (line 31) | MaxBytes = 8192
  type Godspeed (line 37) | type Godspeed struct
    method AddTag (line 93) | func (g *Godspeed) AddTag(tag string) []string {
    method AddTags (line 109) | func (g *Godspeed) AddTags(tags []string) []string {
    method SetNamespace (line 124) | func (g *Godspeed) SetNamespace(ns string) {
  function New (line 61) | func New(host string, port int, autoTruncate bool) (g *Godspeed, err err...
  function NewDefault (line 86) | func NewDefault() (g *Godspeed, err error) {

FILE: vendor/github.com/PagerDuty/godspeed/service_checks.go
  method ServiceCheck (line 27) | func (g *Godspeed) ServiceCheck(name string, status int, fields map[stri...

FILE: vendor/github.com/PagerDuty/godspeed/shared.go
  function trimReserved (line 10) | func trimReserved(s string) string {
  function uniqueTags (line 15) | func uniqueTags(t []string) []string {

FILE: vendor/github.com/PagerDuty/godspeed/stats.go
  method Send (line 19) | func (g *Godspeed) Send(stat, kind string, delta, sampleRate float64, ta...
  method Count (line 70) | func (g *Godspeed) Count(stat string, count float64, tags []string) error {
  method Incr (line 76) | func (g *Godspeed) Incr(stat string, tags []string) error {
  method Decr (line 82) | func (g *Godspeed) Decr(stat string, tags []string) error {
  method Gauge (line 87) | func (g *Godspeed) Gauge(stat string, value float64, tags []string) error {
  method Histogram (line 92) | func (g *Godspeed) Histogram(stat string, value float64, tags []string) ...
  method Timing (line 97) | func (g *Godspeed) Timing(stat string, value float64, tags []string) err...
  method Set (line 102) | func (g *Godspeed) Set(stat string, value float64, tags []string) error {

FILE: vendor/github.com/bradfitz/http2/buffer.go
  type buffer (line 14) | type buffer struct
    method Read (line 29) | func (b *buffer) Read(p []byte) (n int, err error) {
    method Len (line 41) | func (b *buffer) Len() int {
    method Write (line 47) | func (b *buffer) Write(p []byte) (n int, err error) {
    method Close (line 71) | func (b *buffer) Close(err error) {

FILE: vendor/github.com/bradfitz/http2/errors.go
  type ErrCode (line 11) | type ErrCode
    method String (line 47) | func (e ErrCode) String() string {
  constant ErrCodeNo (line 14) | ErrCodeNo                 ErrCode = 0x0
  constant ErrCodeProtocol (line 15) | ErrCodeProtocol           ErrCode = 0x1
  constant ErrCodeInternal (line 16) | ErrCodeInternal           ErrCode = 0x2
  constant ErrCodeFlowControl (line 17) | ErrCodeFlowControl        ErrCode = 0x3
  constant ErrCodeSettingsTimeout (line 18) | ErrCodeSettingsTimeout    ErrCode = 0x4
  constant ErrCodeStreamClosed (line 19) | ErrCodeStreamClosed       ErrCode = 0x5
  constant ErrCodeFrameSize (line 20) | ErrCodeFrameSize          ErrCode = 0x6
  constant ErrCodeRefusedStream (line 21) | ErrCodeRefusedStream      ErrCode = 0x7
  constant ErrCodeCancel (line 22) | ErrCodeCancel             ErrCode = 0x8
  constant ErrCodeCompression (line 23) | ErrCodeCompression        ErrCode = 0x9
  constant ErrCodeConnect (line 24) | ErrCodeConnect            ErrCode = 0xa
  constant ErrCodeEnhanceYourCalm (line 25) | ErrCodeEnhanceYourCalm    ErrCode = 0xb
  constant ErrCodeInadequateSecurity (line 26) | ErrCodeInadequateSecurity ErrCode = 0xc
  constant ErrCodeHTTP11Required (line 27) | ErrCodeHTTP11Required     ErrCode = 0xd
  type ConnectionError (line 56) | type ConnectionError
    method Error (line 58) | func (e ConnectionError) Error() string { return fmt.Sprintf("connecti...
  type StreamError (line 62) | type StreamError struct
    method Error (line 67) | func (e StreamError) Error() string {
  type goAwayFlowError (line 76) | type goAwayFlowError struct
    method Error (line 78) | func (goAwayFlowError) Error() string { return "connection exceeded fl...

FILE: vendor/github.com/bradfitz/http2/flow.go
  type flow (line 11) | type flow struct
    method setConnFlow (line 22) | func (f *flow) setConnFlow(cf *flow) { f.conn = cf }
    method available (line 24) | func (f *flow) available() int32 {
    method take (line 32) | func (f *flow) take(n int32) {
    method add (line 44) | func (f *flow) add(n int32) bool {

FILE: vendor/github.com/bradfitz/http2/frame.go
  constant frameHeaderLen (line 17) | frameHeaderLen = 9
  type FrameType (line 23) | type FrameType
    method String (line 51) | func (t FrameType) String() string {
  constant FrameData (line 26) | FrameData         FrameType = 0x0
  constant FrameHeaders (line 27) | FrameHeaders      FrameType = 0x1
  constant FramePriority (line 28) | FramePriority     FrameType = 0x2
  constant FrameRSTStream (line 29) | FrameRSTStream    FrameType = 0x3
  constant FrameSettings (line 30) | FrameSettings     FrameType = 0x4
  constant FramePushPromise (line 31) | FramePushPromise  FrameType = 0x5
  constant FramePing (line 32) | FramePing         FrameType = 0x6
  constant FrameGoAway (line 33) | FrameGoAway       FrameType = 0x7
  constant FrameWindowUpdate (line 34) | FrameWindowUpdate FrameType = 0x8
  constant FrameContinuation (line 35) | FrameContinuation FrameType = 0x9
  type Flags (line 60) | type Flags
    method Has (line 63) | func (f Flags) Has(v Flags) bool {
  constant FlagDataEndStream (line 70) | FlagDataEndStream Flags = 0x1
  constant FlagDataPadded (line 71) | FlagDataPadded    Flags = 0x8
  constant FlagHeadersEndStream (line 74) | FlagHeadersEndStream  Flags = 0x1
  constant FlagHeadersEndHeaders (line 75) | FlagHeadersEndHeaders Flags = 0x4
  constant FlagHeadersPadded (line 76) | FlagHeadersPadded     Flags = 0x8
  constant FlagHeadersPriority (line 77) | FlagHeadersPriority   Flags = 0x20
  constant FlagSettingsAck (line 80) | FlagSettingsAck Flags = 0x1
  constant FlagPingAck (line 83) | FlagPingAck Flags = 0x1
  constant FlagContinuationEndHeaders (line 86) | FlagContinuationEndHeaders Flags = 0x4
  constant FlagPushPromiseEndHeaders (line 88) | FlagPushPromiseEndHeaders Flags = 0x4
  constant FlagPushPromisePadded (line 89) | FlagPushPromisePadded     Flags = 0x8
  type frameParser (line 121) | type frameParser
  function typeFrameParser (line 136) | func typeFrameParser(t FrameType) frameParser {
  type FrameHeader (line 146) | type FrameHeader struct
    method Header (line 170) | func (h FrameHeader) Header() FrameHeader { return h }
    method String (line 172) | func (h FrameHeader) String() string {
    method checkValid (line 202) | func (h *FrameHeader) checkValid() {
    method invalidate (line 208) | func (h *FrameHeader) invalidate() { h.valid = false }
  function ReadFrameHeader (line 221) | func ReadFrameHeader(r io.Reader) (FrameHeader, error) {
  function readFrameHeader (line 227) | func readFrameHeader(buf []byte, r io.Reader) (FrameHeader, error) {
  type Frame (line 246) | type Frame interface
  type Framer (line 256) | type Framer struct
    method startWrite (line 289) | func (f *Framer) startWrite(ftype FrameType, flags Flags, streamID uin...
    method endWrite (line 303) | func (f *Framer) endWrite() error {
    method writeByte (line 321) | func (f *Framer) writeByte(v byte)     { f.wbuf = append(f.wbuf, v) }
    method writeBytes (line 322) | func (f *Framer) writeBytes(v []byte)  { f.wbuf = append(f.wbuf, v...) }
    method writeUint16 (line 323) | func (f *Framer) writeUint16(v uint16) { f.wbuf = append(f.wbuf, byte(...
    method writeUint32 (line 324) | func (f *Framer) writeUint32(v uint32) {
    method SetMaxReadFrameSize (line 354) | func (fr *Framer) SetMaxReadFrameSize(v uint32) {
    method ReadFrame (line 369) | func (fr *Framer) ReadFrame() (Frame, error) {
    method WriteData (line 454) | func (f *Framer) WriteData(streamID uint32, endStream bool, data []byt...
    method WriteSettings (line 551) | func (f *Framer) WriteSettings(settings ...Setting) error {
    method WriteSettingsAck (line 564) | func (f *Framer) WriteSettingsAck() error {
    method WritePing (line 590) | func (f *Framer) WritePing(ack bool, data [8]byte) error {
    method WriteGoAway (line 633) | func (f *Framer) WriteGoAway(maxStreamID uint32, code ErrCode, debugDa...
    method WriteWindowUpdate (line 696) | func (f *Framer) WriteWindowUpdate(streamID, incr uint32) error {
    method WriteHeaders (line 806) | func (f *Framer) WriteHeaders(p HeadersFrameParam) error {
    method WritePriority (line 894) | func (f *Framer) WritePriority(streamID uint32, p PriorityParam) error {
    method WriteRSTStream (line 929) | func (f *Framer) WriteRSTStream(streamID uint32, code ErrCode) error {
    method WriteContinuation (line 966) | func (f *Framer) WriteContinuation(streamID uint32, endHeaders bool, h...
    method WritePushPromise (line 1061) | func (f *Framer) WritePushPromise(p PushPromiseParam) error {
    method WriteRawFrame (line 1087) | func (f *Framer) WriteRawFrame(t FrameType, flags Flags, streamID uint...
  constant minMaxFrameSize (line 329) | minMaxFrameSize = 1 << 14
  constant maxFrameSize (line 330) | maxFrameSize    = 1<<24 - 1
  function NewFramer (line 334) | func NewFramer(w io.Writer, r io.Reader) *Framer {
  type DataFrame (line 395) | type DataFrame struct
    method StreamEnded (line 400) | func (f *DataFrame) StreamEnded() bool {
    method Data (line 408) | func (f *DataFrame) Data() []byte {
  function parseDataFrame (line 413) | func parseDataFrame(fh FrameHeader, payload []byte) (Frame, error) {
  function validStreamID (line 446) | func validStreamID(streamID uint32) bool {
  type SettingsFrame (line 473) | type SettingsFrame struct
    method IsAck (line 512) | func (f *SettingsFrame) IsAck() bool {
    method Value (line 516) | func (f *SettingsFrame) Value(s SettingID) (v uint32, ok bool) {
    method ForeachSetting (line 531) | func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error {
  function parseSettingsFrame (line 478) | func parseSettingsFrame(fh FrameHeader, p []byte) (Frame, error) {
  type PingFrame (line 573) | type PingFrame struct
  function parsePingFrame (line 578) | func parsePingFrame(fh FrameHeader, payload []byte) (Frame, error) {
  type GoAwayFrame (line 602) | type GoAwayFrame struct
    method DebugData (line 613) | func (f *GoAwayFrame) DebugData() []byte {
  function parseGoAwayFrame (line 618) | func parseGoAwayFrame(fh FrameHeader, p []byte) (Frame, error) {
  type UnknownFrame (line 643) | type UnknownFrame struct
    method Payload (line 653) | func (f *UnknownFrame) Payload() []byte {
  function parseUnknownFrame (line 658) | func parseUnknownFrame(fh FrameHeader, p []byte) (Frame, error) {
  type WindowUpdateFrame (line 664) | type WindowUpdateFrame struct
  function parseWindowUpdateFrame (line 669) | func parseWindowUpdateFrame(fh FrameHeader, p []byte) (Frame, error) {
  type HeadersFrame (line 708) | type HeadersFrame struct
    method HeaderBlockFragment (line 717) | func (f *HeadersFrame) HeaderBlockFragment() []byte {
    method HeadersEnded (line 722) | func (f *HeadersFrame) HeadersEnded() bool {
    method StreamEnded (line 726) | func (f *HeadersFrame) StreamEnded() bool {
    method HasPriority (line 730) | func (f *HeadersFrame) HasPriority() bool {
  function parseHeadersFrame (line 734) | func parseHeadersFrame(fh FrameHeader, p []byte) (_ Frame, err error) {
  type HeadersFrameParam (line 772) | type HeadersFrameParam struct
  type PriorityFrame (line 845) | type PriorityFrame struct
  type PriorityParam (line 851) | type PriorityParam struct
    method IsZero (line 867) | func (p PriorityParam) IsZero() bool {
  function parsePriorityFrame (line 871) | func parsePriorityFrame(fh FrameHeader, payload []byte) (Frame, error) {
  type RSTStreamFrame (line 910) | type RSTStreamFrame struct
  function parseRSTStreamFrame (line 915) | func parseRSTStreamFrame(fh FrameHeader, p []byte) (Frame, error) {
  type ContinuationFrame (line 940) | type ContinuationFrame struct
    method StreamEnded (line 949) | func (f *ContinuationFrame) StreamEnded() bool {
    method HeaderBlockFragment (line 953) | func (f *ContinuationFrame) HeaderBlockFragment() []byte {
    method HeadersEnded (line 958) | func (f *ContinuationFrame) HeadersEnded() bool {
  function parseContinuationFrame (line 945) | func parseContinuationFrame(fh FrameHeader, p []byte) (Frame, error) {
  type PushPromiseFrame (line 981) | type PushPromiseFrame struct
    method HeaderBlockFragment (line 987) | func (f *PushPromiseFrame) HeaderBlockFragment() []byte {
    method HeadersEnded (line 992) | func (f *PushPromiseFrame) HeadersEnded() bool {
  function parsePushPromise (line 996) | func parsePushPromise(fh FrameHeader, p []byte) (_ Frame, err error) {
  type PushPromiseParam (line 1033) | type PushPromiseParam struct
  function readByte (line 1093) | func readByte(p []byte) (remain []byte, b byte, err error) {
  function readUint32 (line 1100) | func readUint32(p []byte) (remain []byte, v uint32, err error) {
  type streamEnder (line 1107) | type streamEnder interface
  type headersEnder (line 1111) | type headersEnder interface

FILE: vendor/github.com/bradfitz/http2/gotrack.go
  type goroutineLock (line 25) | type goroutineLock
    method check (line 34) | func (g goroutineLock) check() {
    method checkNotOn (line 43) | func (g goroutineLock) checkNotOn() {
  function newGoroutineLock (line 27) | func newGoroutineLock() goroutineLock {
  function curGoroutineID (line 54) | func curGoroutineID() uint64 {
  function parseUintBytes (line 81) | func parseUintBytes(s []byte, base int, bitSize int) (n uint64, err erro...
  function cutoff64 (line 168) | func cutoff64(base int) uint64 {

FILE: vendor/github.com/bradfitz/http2/h2i/h2i.go
  type command (line 50) | type command struct
  function usage (line 78) | func usage() {
  function withPort (line 85) | func withPort(host string) string {
  type h2i (line 93) | type h2i struct
    method Main (line 135) | func (app *h2i) Main() error {
    method logf (line 240) | func (app *h2i) logf(format string, args ...interface{}) {
    method readConsole (line 244) | func (app *h2i) readConsole() error {
    method cmdQuit (line 292) | func (a *h2i) cmdQuit(args []string) error {
    method cmdSettings (line 300) | func (a *h2i) cmdSettings(args []string) error {
    method cmdPing (line 350) | func (app *h2i) cmdPing(args []string) error {
    method cmdHeaders (line 364) | func (app *h2i) cmdHeaders(args []string) error {
    method readFrames (line 409) | func (app *h2i) readFrames() error {
    method onNewHeaderField (line 448) | func (app *h2i) onNewHeaderField(f hpack.HeaderField) {
    method encodeHeaders (line 455) | func (app *h2i) encodeHeaders(req *http.Request) []byte {
    method writeHeader (line 486) | func (app *h2i) writeHeader(name, value string) {
  function main (line 109) | func main() {
  function lookupCommand (line 272) | func lookupCommand(prefix string) (name string, c command, ok bool) {
  function settingByName (line 334) | func settingByName(name string) (http2.SettingID, bool) {

FILE: vendor/github.com/bradfitz/http2/headermap.go
  function init (line 20) | func init() {
  function lowerHeader (line 75) | func lowerHeader(v string) string {

FILE: vendor/github.com/bradfitz/http2/hpack/encode.go
  constant uint32Max (line 13) | uint32Max              = ^uint32(0)
  constant initialHeaderTableSize (line 14) | initialHeaderTableSize = 4096
  type Encoder (line 17) | type Encoder struct
    method WriteField (line 50) | func (e *Encoder) WriteField(f HeaderField) error {
    method searchTable (line 91) | func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch...
    method SetMaxDynamicTableSize (line 120) | func (e *Encoder) SetMaxDynamicTableSize(v uint32) {
    method SetMaxDynamicTableSizeLimit (line 138) | func (e *Encoder) SetMaxDynamicTableSizeLimit(v uint32) {
    method shouldIndex (line 147) | func (e *Encoder) shouldIndex(f HeaderField) bool {
  function NewEncoder (line 36) | func NewEncoder(w io.Writer) *Encoder {
  function appendIndexed (line 153) | func appendIndexed(dst []byte, i uint64) []byte {
  function appendNewName (line 167) | func appendNewName(dst []byte, f HeaderField, indexing bool) []byte {
  function appendIndexedName (line 180) | func appendIndexedName(dst []byte, f HeaderField, i uint64, indexing boo...
  function appendTableSize (line 195) | func appendTableSize(dst []byte, v uint32) []byte {
  function appendVarInt (line 207) | func appendVarInt(dst []byte, n byte, i uint64) []byte {
  function appendHpackString (line 225) | func appendHpackString(dst []byte, s string) []byte {
  function encodeTypeByte (line 244) | func encodeTypeByte(indexing, sensitive bool) byte {

FILE: vendor/github.com/bradfitz/http2/hpack/hpack.go
  type DecodingError (line 19) | type DecodingError struct
    method Error (line 23) | func (de DecodingError) Error() string {
  type InvalidIndexError (line 29) | type InvalidIndexError
    method Error (line 31) | func (e InvalidIndexError) Error() string {
  type HeaderField (line 37) | type HeaderField struct
    method size (line 45) | func (hf *HeaderField) size() uint32 {
  type Decoder (line 63) | type Decoder struct
    method SetMaxDynamicTableSize (line 87) | func (d *Decoder) SetMaxDynamicTableSize(v uint32) {
    method SetAllowedMaxDynamicTableSize (line 94) | func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32) {
    method maxTableIndex (line 187) | func (d *Decoder) maxTableIndex() int {
    method at (line 191) | func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
    method DecodeFull (line 209) | func (d *Decoder) DecodeFull(p []byte) ([]HeaderField, error) {
    method Close (line 223) | func (d *Decoder) Close() error {
    method Write (line 231) | func (d *Decoder) Write(p []byte) (n int, err error) {
    method parseHeaderFieldRepr (line 282) | func (d *Decoder) parseHeaderFieldRepr() error {
    method parseFieldIndexed (line 316) | func (d *Decoder) parseFieldIndexed() error {
    method parseFieldLiteral (line 332) | func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
    method parseDynamicTableSizeUpdate (line 366) | func (d *Decoder) parseDynamicTableSizeUpdate() error {
  function NewDecoder (line 75) | func NewDecoder(maxSize uint32, emitFunc func(f HeaderField)) *Decoder {
  type dynamicTable (line 98) | type dynamicTable struct
    method setMaxSize (line 109) | func (dt *dynamicTable) setMaxSize(v uint32) {
    method add (line 123) | func (dt *dynamicTable) add(f HeaderField) {
    method evict (line 130) | func (dt *dynamicTable) evict() {
    method search (line 164) | func (dt *dynamicTable) search(f HeaderField) (i uint64, nameValueMatc...
  function constantTimeStringCompare (line 146) | func constantTimeStringCompare(a, b string) bool {
  type indexType (line 267) | type indexType
    method indexed (line 275) | func (v indexType) indexed() bool   { return v == indexedTrue }
    method sensitive (line 276) | func (v indexType) sensitive() bool { return v == indexedNever }
  constant indexedTrue (line 270) | indexedTrue indexType = iota
  constant indexedFalse (line 271) | indexedFalse
  constant indexedNever (line 272) | indexedNever
  function readVarInt (line 390) | func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
  function readString (line 423) | func readString(p []byte) (s string, remain []byte, err error) {

FILE: vendor/github.com/bradfitz/http2/hpack/huffman.go
  function HuffmanDecode (line 21) | func HuffmanDecode(w io.Writer, v []byte) (int, error) {
  type node (line 54) | type node struct
  function newInternalNode (line 63) | func newInternalNode() *node {
  function init (line 69) | func init() {
  function addDecoderNode (line 78) | func addDecoderNode(sym byte, code uint32, codeLen uint8) {
  function AppendHuffmanString (line 97) | func AppendHuffmanString(dst []byte, s string) []byte {
  function HuffmanEncodeLength (line 121) | func HuffmanEncodeLength(s string) uint64 {
  function appendByteToHuffmanCode (line 133) | func appendByteToHuffmanCode(dst []byte, rembits uint8, c byte) ([]byte,...

FILE: vendor/github.com/bradfitz/http2/hpack/tables.go
  function pair (line 8) | func pair(name, value string) HeaderField {

FILE: vendor/github.com/bradfitz/http2/http2.go
  constant ClientPreface (line 33) | ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
  constant initialMaxFrameSize (line 37) | initialMaxFrameSize = 16384
  constant NextProtoTLS (line 41) | NextProtoTLS = "h2"
  constant initialHeaderTableSize (line 44) | initialHeaderTableSize = 4096
  constant initialWindowSize (line 46) | initialWindowSize = 65535
  constant defaultMaxReadFrameSize (line 48) | defaultMaxReadFrameSize = 1 << 20
  type streamState (line 55) | type streamState
    method String (line 77) | func (st streamState) String() string {
  constant stateIdle (line 58) | stateIdle streamState = iota
  constant stateOpen (line 59) | stateOpen
  constant stateHalfClosedLocal (line 60) | stateHalfClosedLocal
  constant stateHalfClosedRemote (line 61) | stateHalfClosedRemote
  constant stateResvLocal (line 62) | stateResvLocal
  constant stateResvRemote (line 63) | stateResvRemote
  constant stateClosed (line 64) | stateClosed
  type Setting (line 82) | type Setting struct
    method String (line 91) | func (s Setting) String() string {
    method Valid (line 96) | func (s Setting) Valid() error {
  type SettingID (line 117) | type SettingID
    method String (line 137) | func (s SettingID) String() string {
  constant SettingHeaderTableSize (line 120) | SettingHeaderTableSize      SettingID = 0x1
  constant SettingEnablePush (line 121) | SettingEnablePush           SettingID = 0x2
  constant SettingMaxConcurrentStreams (line 122) | SettingMaxConcurrentStreams SettingID = 0x3
  constant SettingInitialWindowSize (line 123) | SettingInitialWindowSize    SettingID = 0x4
  constant SettingMaxFrameSize (line 124) | SettingMaxFrameSize         SettingID = 0x5
  constant SettingMaxHeaderListSize (line 125) | SettingMaxHeaderListSize    SettingID = 0x6
  function validHeader (line 144) | func validHeader(v string) bool {
  function init (line 163) | func init() {
  function httpCodeString (line 171) | func httpCodeString(code int) string {
  type stringWriter (line 179) | type stringWriter interface
  type gate (line 184) | type gate
    method Done (line 186) | func (g gate) Done() { g <- struct{}{} }
    method Wait (line 187) | func (g gate) Wait() { <-g }
  type closeWaiter (line 190) | type closeWaiter
    method Init (line 196) | func (cw *closeWaiter) Init() {
    method Close (line 201) | func (cw closeWaiter) Close() {
    method Wait (line 206) | func (cw closeWaiter) Wait() {
  type bufferedWriter (line 213) | type bufferedWriter struct
    method Write (line 230) | func (w *bufferedWriter) Write(p []byte) (n int, err error) {
    method Flush (line 239) | func (w *bufferedWriter) Flush() error {
  function newBufferedWriter (line 218) | func newBufferedWriter(w io.Writer) *bufferedWriter {

FILE: vendor/github.com/bradfitz/http2/pipe.go
  type pipe (line 12) | type pipe struct
    method Read (line 20) | func (r *pipe) Read(p []byte) (n int, err error) {
    method Write (line 31) | func (w *pipe) Write(p []byte) (n int, err error) {
    method Close (line 38) | func (c *pipe) Close(err error) {

FILE: vendor/github.com/bradfitz/http2/server.go
  constant prefaceTimeout (line 62) | prefaceTimeout        = 10 * time.Second
  constant firstSettingsTimeout (line 63) | firstSettingsTimeout  = 2 * time.Second
  constant handlerChunkWriteSize (line 64) | handlerChunkWriteSize = 4 << 10
  constant defaultMaxStreams (line 65) | defaultMaxStreams     = 250
  type Server (line 91) | type Server struct
    method maxReadFrameSize (line 117) | func (s *Server) maxReadFrameSize() uint32 {
    method maxConcurrentStreams (line 124) | func (s *Server) maxConcurrentStreams() uint32 {
    method handleConn (line 195) | func (srv *Server) handleConn(hs *http.Server, c net.Conn, h http.Hand...
  function ConfigureServer (line 136) | func ConfigureServer(s *http.Server, conf *Server) {
  function isBadCipher (line 281) | func isBadCipher(cipher uint16) bool {
  type frameAndGate (line 317) | type frameAndGate struct
  type serverConn (line 322) | type serverConn struct
    method rejectConn (line 304) | func (sc *serverConn) rejectConn(err ErrCode, debug string) {
    method Framer (line 412) | func (sc *serverConn) Framer() *Framer  { return sc.framer }
    method CloseConn (line 413) | func (sc *serverConn) CloseConn() error { return sc.conn.Close() }
    method Flush (line 414) | func (sc *serverConn) Flush() error     { return sc.bw.Flush() }
    method HeaderEncoder (line 415) | func (sc *serverConn) HeaderEncoder() (*hpack.Encoder, *bytes.Buffer) {
    method state (line 419) | func (sc *serverConn) state(streamID uint32) (streamState, *stream) {
    method vlogf (line 437) | func (sc *serverConn) vlogf(format string, args ...interface{}) {
    method logf (line 443) | func (sc *serverConn) logf(format string, args ...interface{}) {
    method condlogf (line 451) | func (sc *serverConn) condlogf(err error, format string, args ...inter...
    method onNewHeaderField (line 464) | func (sc *serverConn) onNewHeaderField(f hpack.HeaderField) {
    method canonicalHeader (line 515) | func (sc *serverConn) canonicalHeader(v string) string {
    method readFrames (line 535) | func (sc *serverConn) readFrames() {
    method writeFrameAsync (line 558) | func (sc *serverConn) writeFrameAsync(wm frameWriteMsg) {
    method closeAllStreamsOnConnClose (line 570) | func (sc *serverConn) closeAllStreamsOnConnClose() {
    method stopShutdownTimer (line 577) | func (sc *serverConn) stopShutdownTimer() {
    method notePanic (line 584) | func (sc *serverConn) notePanic() {
    method serve (line 598) | func (sc *serverConn) serve() {
    method readPreface (line 666) | func (sc *serverConn) readPreface() error {
    method writeDataFromHandler (line 704) | func (sc *serverConn) writeDataFromHandler(stream *stream, writeData *...
    method writeFrameFromHandler (line 727) | func (sc *serverConn) writeFrameFromHandler(wm frameWriteMsg) {
    method writeFrame (line 744) | func (sc *serverConn) writeFrame(wm frameWriteMsg) {
    method startFrameWrite (line 753) | func (sc *serverConn) startFrameWrite(wm frameWriteMsg) {
    method scheduleFrameWrite (line 812) | func (sc *serverConn) scheduleFrameWrite() {
    method goAway (line 845) | func (sc *serverConn) goAway(code ErrCode) {
    method shutDownIn (line 862) | func (sc *serverConn) shutDownIn(d time.Duration) {
    method resetStream (line 868) | func (sc *serverConn) resetStream(se StreamError) {
    method curHeaderStreamID (line 880) | func (sc *serverConn) curHeaderStreamID() uint32 {
    method processFrameFromReader (line 892) | func (sc *serverConn) processFrameFromReader(fg frameAndGate, fgValid ...
    method processFrame (line 947) | func (sc *serverConn) processFrame(f Frame) error {
    method processPing (line 993) | func (sc *serverConn) processPing(f *PingFrame) error {
    method processWindowUpdate (line 1012) | func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
    method processResetStream (line 1037) | func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {
    method closeStream (line 1056) | func (sc *serverConn) closeStream(st *stream, err error) {
    method processSettings (line 1071) | func (sc *serverConn) processSettings(f *SettingsFrame) error {
    method processSetting (line 1091) | func (sc *serverConn) processSetting(s Setting) error {
    method processSettingInitialWindowSize (line 1119) | func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
    method processData (line 1147) | func (sc *serverConn) processData(f *DataFrame) error {
    method processHeaders (line 1199) | func (sc *serverConn) processHeaders(f *HeadersFrame) error {
    method processContinuation (line 1246) | func (sc *serverConn) processContinuation(f *ContinuationFrame) error {
    method processHeaderBlockFragment (line 1255) | func (sc *serverConn) processHeaderBlockFragment(st *stream, frag []by...
    method processPriority (line 1298) | func (sc *serverConn) processPriority(f *PriorityFrame) error {
    method resetPendingRequest (line 1342) | func (sc *serverConn) resetPendingRequest() {
    method newWriterAndRequest (line 1347) | func (sc *serverConn) newWriterAndRequest() (*responseWriter, *http.Re...
    method runHandler (line 1430) | func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request) {
    method writeHeaders (line 1438) | func (sc *serverConn) writeHeaders(st *stream, headerData *writeResHea...
    method write100ContinueHeaders (line 1465) | func (sc *serverConn) write100ContinueHeaders(st *stream) {
    method noteBodyReadFromHandler (line 1482) | func (sc *serverConn) noteBodyReadFromHandler(st *stream, n int) {
    method noteBodyRead (line 1487) | func (sc *serverConn) noteBodyRead(st *stream, n int) {
    method sendWindowUpdate (line 1498) | func (sc *serverConn) sendWindowUpdate(st *stream, n int) {
    method sendWindowUpdate32 (line 1514) | func (sc *serverConn) sendWindowUpdate32(st *stream, n int32) {
  type requestParam (line 376) | type requestParam struct
  type stream (line 394) | type stream struct
  function adjustStreamPriority (line 1303) | func adjustStreamPriority(streams map[uint32]*stream, streamID uint32, p...
  type bodyReadMsg (line 1474) | type bodyReadMsg struct
  type requestBody (line 1541) | type requestBody struct
    method Close (line 1549) | func (b *requestBody) Close() error {
    method Read (line 1557) | func (b *requestBody) Read(p []byte) (n int, err error) {
  type responseWriter (line 1578) | type responseWriter struct
    method Flush (line 1662) | func (w *responseWriter) Flush() {
    method CloseNotify (line 1681) | func (w *responseWriter) CloseNotify() <-chan bool {
    method Header (line 1700) | func (w *responseWriter) Header() http.Header {
    method WriteHeader (line 1711) | func (w *responseWriter) WriteHeader(code int) {
    method Write (line 1747) | func (w *responseWriter) Write(p []byte) (n int, err error) {
    method WriteString (line 1751) | func (w *responseWriter) WriteString(s string) (n int, err error) {
    method write (line 1756) | func (w *responseWriter) write(lenData int, dataB []byte, dataS string...
    method handlerDone (line 1771) | func (w *responseWriter) handlerDone() {
  type responseWriterState (line 1589) | type responseWriterState struct
    method writeChunk (line 1623) | func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
    method writeHeader (line 1719) | func (rws *responseWriterState) writeHeader(code int) {
  type chunkWriter (line 1613) | type chunkWriter struct
    method Write (line 1615) | func (cw chunkWriter) Write(p []byte) (n int, err error) { return cw.r...
  function cloneHeader (line 1729) | func cloneHeader(h http.Header) http.Header {

FILE: vendor/github.com/bradfitz/http2/transport.go
  type Transport (line 25) | type Transport struct
    method RoundTrip (line 84) | func (t *Transport) RoundTrip(req *http.Request) (*http.Response, erro...
    method CloseIdleConnections (line 117) | func (t *Transport) CloseIdleConnections() {
    method removeClientConn (line 134) | func (t *Transport) removeClientConn(cc *clientConn) {
    method getClientConn (line 161) | func (t *Transport) getClientConn(host, port string) (*clientConn, err...
    method newClientConn (line 183) | func (t *Transport) newClientConn(host, port, key string) (*clientConn...
  type clientConn (line 35) | type clientConn struct
    method setGoAway (line 271) | func (cc *clientConn) setGoAway(f *GoAwayFrame) {
    method canTakeNewRequest (line 277) | func (cc *clientConn) canTakeNewRequest() bool {
    method closeIfIdle (line 285) | func (cc *clientConn) closeIfIdle() {
    method roundTrip (line 298) | func (cc *clientConn) roundTrip(req *http.Request) (*http.Response, er...
    method encodeHeaders (line 355) | func (cc *clientConn) encodeHeaders(req *http.Request) []byte {
    method writeHeader (line 386) | func (cc *clientConn) writeHeader(name, value string) {
    method newStream (line 397) | func (cc *clientConn) newStream() *clientStream {
    method streamByID (line 407) | func (cc *clientConn) streamByID(id uint32, andRemove bool) *clientStr...
    method readLoop (line 418) | func (cc *clientConn) readLoop() {
    method onNewHeaderField (line 534) | func (cc *clientConn) onNewHeaderField(f hpack.HeaderField) {
  type clientStream (line 63) | type clientStream struct
  type stickyErrWriter (line 70) | type stickyErrWriter struct
    method Write (line 75) | func (sew stickyErrWriter) Write(p []byte) (n int, err error) {
  function shouldRetryRequest (line 129) | func shouldRetryRequest(err error) bool {
  function filterOutClientConn (line 151) | func filterOutClientConn(in []*clientConn, exclude *clientConn) []*clien...
  type resAndError (line 391) | type resAndError struct

FILE: vendor/github.com/bradfitz/http2/write.go
  type writeFramer (line 20) | type writeFramer interface
  type writeContext (line 30) | type writeContext interface
  function endsStream (line 41) | func endsStream(w writeFramer) bool {
  type flushFrameWriter (line 51) | type flushFrameWriter struct
    method writeFrame (line 53) | func (flushFrameWriter) writeFrame(ctx writeContext) error {
  type writeSettings (line 57) | type writeSettings
    method writeFrame (line 59) | func (s writeSettings) writeFrame(ctx writeContext) error {
  type writeGoAway (line 63) | type writeGoAway struct
    method writeFrame (line 68) | func (p *writeGoAway) writeFrame(ctx writeContext) error {
  type writeData (line 78) | type writeData struct
    method String (line 84) | func (w *writeData) String() string {
    method writeFrame (line 88) | func (w *writeData) writeFrame(ctx writeContext) error {
  method writeFrame (line 92) | func (se StreamError) writeFrame(ctx writeContext) error {
  type writePingAck (line 96) | type writePingAck struct
    method writeFrame (line 98) | func (w writePingAck) writeFrame(ctx writeContext) error {
  type writeSettingsAck (line 102) | type writeSettingsAck struct
    method writeFrame (line 104) | func (writeSettingsAck) writeFrame(ctx writeContext) error {
  type writeResHeaders (line 110) | type writeResHeaders struct
    method writeFrame (line 120) | func (w *writeResHeaders) writeFrame(ctx writeContext) error {
  type write100ContinueHeadersFrame (line 181) | type write100ContinueHeadersFrame struct
    method writeFrame (line 185) | func (w write100ContinueHeadersFrame) writeFrame(ctx writeContext) err...
  type writeWindowUpdate (line 197) | type writeWindowUpdate struct
    method writeFrame (line 202) | func (wu writeWindowUpdate) writeFrame(ctx writeContext) error {

FILE: vendor/github.com/bradfitz/http2/writesched.go
  type frameWriteMsg (line 13) | type frameWriteMsg struct
    method String (line 28) | func (wm frameWriteMsg) String() string {
  type writeScheduler (line 44) | type writeScheduler struct
    method putEmptyQueue (line 67) | func (ws *writeScheduler) putEmptyQueue(q *writeQueue) {
    method getEmptyQueue (line 74) | func (ws *writeScheduler) getEmptyQueue() *writeQueue {
    method empty (line 84) | func (ws *writeScheduler) empty() bool { return ws.zero.empty() && len...
    method add (line 86) | func (ws *writeScheduler) add(wm frameWriteMsg) {
    method streamQueue (line 95) | func (ws *writeScheduler) streamQueue(streamID uint32) *writeQueue {
    method take (line 110) | func (ws *writeScheduler) take() (wm frameWriteMsg, ok bool) {
    method zeroCanSend (line 153) | func (ws *writeScheduler) zeroCanSend() {
    method streamWritableBytes (line 164) | func (ws *writeScheduler) streamWritableBytes(q *writeQueue) int32 {
    method takeFrom (line 183) | func (ws *writeScheduler) takeFrom(id uint32, q *writeQueue) (wm frame...
    method forgetStream (line 233) | func (ws *writeScheduler) forgetStream(id uint32) {
  type writeQueue (line 248) | type writeQueue struct
    method streamID (line 253) | func (q *writeQueue) streamID() uint32 { return q.s[0].stream.id }
    method empty (line 255) | func (q *writeQueue) empty() bool { return len(q.s) == 0 }
    method push (line 257) | func (q *writeQueue) push(wm frameWriteMsg) {
    method head (line 262) | func (q *writeQueue) head() frameWriteMsg {
    method shift (line 269) | func (q *writeQueue) shift() frameWriteMsg {
    method firstIsNoCost (line 281) | func (q *writeQueue) firstIsNoCost() bool {

FILE: vendor/github.com/golang/glog/glog.go
  type severity (line 95) | type severity
    method get (line 118) | func (s *severity) get() severity {
    method set (line 123) | func (s *severity) set(val severity) {
    method String (line 128) | func (s *severity) String() string {
    method Get (line 133) | func (s *severity) Get() interface{} {
    method Set (line 138) | func (s *severity) Set(value string) error {
  constant infoLog (line 101) | infoLog severity = iota
  constant warningLog (line 102) | warningLog
  constant errorLog (line 103) | errorLog
  constant fatalLog (line 104) | fatalLog
  constant numSeverity (line 105) | numSeverity = 4
  constant severityChar (line 108) | severityChar = "IWEF"
  function severityByName (line 154) | func severityByName(s string) (severity, bool) {
  type OutputStats (line 165) | type OutputStats struct
    method Lines (line 171) | func (s *OutputStats) Lines() int64 {
    method Bytes (line 176) | func (s *OutputStats) Bytes() int64 {
  type Level (line 204) | type Level
    method get (line 207) | func (l *Level) get() Level {
    method set (line 212) | func (l *Level) set(val Level) {
    method String (line 217) | func (l *Level) String() string {
    method Get (line 222) | func (l *Level) Get() interface{} {
    method Set (line 227) | func (l *Level) Set(value string) error {
  type moduleSpec (line 239) | type moduleSpec struct
    method String (line 261) | func (m *moduleSpec) String() string {
    method Get (line 277) | func (m *moduleSpec) Get() interface{} {
    method Set (line 284) | func (m *moduleSpec) Set(value string) error {
  type modulePat (line 245) | type modulePat struct
    method match (line 253) | func (m *modulePat) match(file string) bool {
  function isLiteral (line 317) | func isLiteral(pattern string) bool {
  type traceLocation (line 322) | type traceLocation struct
    method isSet (line 329) | func (t *traceLocation) isSet() bool {
    method match (line 336) | func (t *traceLocation) match(file string, line int) bool {
    method String (line 346) | func (t *traceLocation) String() string {
    method Get (line 355) | func (t *traceLocation) Get() interface{} {
    method Set (line 363) | func (t *traceLocation) Set(value string) error {
  type flushSyncWriter (line 392) | type flushSyncWriter interface
  function init (line 398) | func init() {
  function Flush (line 414) | func Flush() {
  type loggingT (line 419) | type loggingT struct
    method setVState (line 469) | func (l *loggingT) setVState(verbosity Level, filter []modulePat, setF...
    method getBuffer (line 488) | func (l *loggingT) getBuffer() *buffer {
    method putBuffer (line 505) | func (l *loggingT) putBuffer(b *buffer) {
    method header (line 535) | func (l *loggingT) header(s severity, depth int) (*buffer, string, int) {
    method formatHeader (line 550) | func (l *loggingT) formatHeader(s severity, file string, line int) *bu...
    method println (line 630) | func (l *loggingT) println(s severity, args ...interface{}) {
    method print (line 636) | func (l *loggingT) print(s severity, args ...interface{}) {
    method printDepth (line 640) | func (l *loggingT) printDepth(s severity, depth int, args ...interface...
    method printf (line 649) | func (l *loggingT) printf(s severity, format string, args ...interface...
    method printWithFileLine (line 661) | func (l *loggingT) printWithFileLine(s severity, file string, line int...
    method output (line 671) | func (l *loggingT) output(s severity, buf *buffer, file string, line i...
    method exit (line 784) | func (l *loggingT) exit(err error) {
    method createFiles (line 858) | func (l *loggingT) createFiles(sev severity) error {
    method flushDaemon (line 878) | func (l *loggingT) flushDaemon() {
    method lockAndFlushAll (line 885) | func (l *loggingT) lockAndFlushAll() {
    method flushAll (line 893) | func (l *loggingT) flushAll() {
    method setV (line 958) | func (l *loggingT) setV(pc uintptr) Level {
  type buffer (line 459) | type buffer struct
    method twoDigits (line 594) | func (buf *buffer) twoDigits(i, d int) {
    method nDigits (line 603) | func (buf *buffer) nDigits(n, i, d int, pad byte) {
    method someDigits (line 615) | func (buf *buffer) someDigits(i, d int) int {
  constant digits (line 591) | digits = "0123456789"
  function timeoutFlush (line 743) | func timeoutFlush(timeout time.Duration) {
  function stacks (line 757) | func stacks(all bool) []byte {
  type syncBuffer (line 799) | type syncBuffer struct
    method Sync (line 807) | func (sb *syncBuffer) Sync() error {
    method Write (line 811) | func (sb *syncBuffer) Write(p []byte) (n int, err error) {
    method rotateFile (line 826) | func (sb *syncBuffer) rotateFile(now time.Time) error {
  constant bufferSize (line 854) | bufferSize = 256 * 1024
  constant flushInterval (line 875) | flushInterval = 30 * time.Second
  function CopyStandardLogTo (line 911) | func CopyStandardLogTo(name string) {
  type logBridge (line 924) | type logBridge
    method Write (line 928) | func (lb logBridge) Write(b []byte) (n int, err error) {
  type Verbose (line 980) | type Verbose
    method Info (line 1027) | func (v Verbose) Info(args ...interface{}) {
    method Infoln (line 1035) | func (v Verbose) Infoln(args ...interface{}) {
    method Infof (line 1043) | func (v Verbose) Infof(format string, args ...interface{}) {
  function V (line 996) | func V(level Level) Verbose {
  function Info (line 1051) | func Info(args ...interface{}) {
  function InfoDepth (line 1057) | func InfoDepth(depth int, args ...interface{}) {
  function Infoln (line 1063) | func Infoln(args ...interface{}) {
  function Infof (line 1069) | func Infof(format string, args ...interface{}) {
  function Warning (line 1075) | func Warning(args ...interface{}) {
  function WarningDepth (line 1081) | func WarningDepth(depth int, args ...interface{}) {
  function Warningln (line 1087) | func Warningln(args ...interface{}) {
  function Warningf (line 1093) | func Warningf(format string, args ...interface{}) {
  function Error (line 1099) | func Error(args ...interface{}) {
  function ErrorDepth (line 1105) | func ErrorDepth(depth int, args ...interface{}) {
  function Errorln (line 1111) | func Errorln(args ...interface{}) {
  function Errorf (line 1117) | func Errorf(format string, args ...interface{}) {
  function Fatal (line 1124) | func Fatal(args ...interface{}) {
  function FatalDepth (line 1130) | func FatalDepth(depth int, args ...interface{}) {
  function Fatalln (line 1137) | func Fatalln(args ...interface{}) {
  function Fatalf (line 1144) | func Fatalf(format string, args ...interface{}) {
  function Exit (line 1154) | func Exit(args ...interface{}) {
  function ExitDepth (line 1161) | func ExitDepth(depth int, args ...interface{}) {
  function Exitln (line 1167) | func Exitln(args ...interface{}) {
  function Exitf (line 1174) | func Exitf(format string, args ...interface{}) {

FILE: vendor/github.com/golang/glog/glog_file.go
  function createLogDirs (line 43) | func createLogDirs() {
  function init (line 57) | func init() {
  function shortHostname (line 74) | func shortHostname(hostname string) string {
  function logName (line 83) | func logName(tag string, t time.Time) (name, link string) {
  function create (line 105) | func create(tag string, t time.Time) (f *os.File, filename string, err e...

FILE: vendor/github.com/golang/protobuf/proto/clone.go
  function Clone (line 44) | func Clone(pb Message) Message {
  function Merge (line 60) | func Merge(dst, src Message) {
  function mergeStruct (line 77) | func mergeStruct(out, in reflect.Value) {
  function mergeAny (line 101) | func mergeAny(out, in reflect.Value) {
  function mergeExtension (line 182) | func mergeExtension(out, in map[int32]Extension) {

FILE: vendor/github.com/golang/protobuf/proto/decode.go
  function DecodeVarint (line 59) | func DecodeVarint(buf []byte) (x uint64, n int) {
  method DecodeVarint (line 81) | func (p *Buffer) DecodeVarint() (x uint64, err error) {
  method DecodeFixed64 (line 109) | func (p *Buffer) DecodeFixed64() (x uint64, err error) {
  method DecodeFixed32 (line 132) | func (p *Buffer) DecodeFixed32() (x uint64, err error) {
  method DecodeZigzag64 (line 151) | func (p *Buffer) DecodeZigzag64() (x uint64, err error) {
  method DecodeZigzag32 (line 163) | func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
  method DecodeRawBytes (line 178) | func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) {
  method DecodeStringBytes (line 208) | func (p *Buffer) DecodeStringBytes() (s string, err error) {
  method skipAndSave (line 219) | func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structP...
  method skip (line 246) | func (o *Buffer) skip(t reflect.Type, tag, wire int) error {
  type Unmarshaler (line 287) | type Unmarshaler interface
  function Unmarshal (line 298) | func Unmarshal(buf []byte, pb Message) error {
  function UnmarshalMerge (line 309) | func UnmarshalMerge(buf []byte, pb Message) error {
  method Unmarshal (line 321) | func (p *Buffer) Unmarshal(pb Message) error {
  method unmarshalType (line 344) | func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, ...
  constant boolPoolSize (line 448) | boolPoolSize   = 16
  constant uint32PoolSize (line 449) | uint32PoolSize = 8
  constant uint64PoolSize (line 450) | uint64PoolSize = 4
  method dec_bool (line 454) | func (o *Buffer) dec_bool(p *Properties, base structPointer) error {
  method dec_proto3_bool (line 468) | func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error {
  method dec_int32 (line 478) | func (o *Buffer) dec_int32(p *Properties, base structPointer) error {
  method dec_proto3_int32 (line 487) | func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) err...
  method dec_int64 (line 497) | func (o *Buffer) dec_int64(p *Properties, base structPointer) error {
  method dec_proto3_int64 (line 506) | func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) err...
  method dec_string (line 516) | func (o *Buffer) dec_string(p *Properties, base structPointer) error {
  method dec_proto3_string (line 525) | func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) er...
  method dec_slice_byte (line 535) | func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error {
  method dec_slice_bool (line 545) | func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error {
  method dec_slice_packed_bool (line 556) | func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer...
  method dec_slice_int32 (line 579) | func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error {
  method dec_slice_packed_int32 (line 589) | func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointe...
  method dec_slice_int64 (line 613) | func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error {
  method dec_slice_packed_int64 (line 624) | func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointe...
  method dec_slice_string (line 648) | func (o *Buffer) dec_slice_string(p *Properties, base structPointer) err...
  method dec_slice_slice_byte (line 659) | func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer)...
  method dec_new_map (line 670) | func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
  method dec_struct_group (line 742) | func (o *Buffer) dec_struct_group(p *Properties, base structPointer) err...
  method dec_struct_message (line 753) | func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (...
  method dec_slice_struct_message (line 785) | func (o *Buffer) dec_slice_struct_message(p *Properties, base structPoin...
  method dec_slice_struct_group (line 790) | func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointe...
  method dec_slice_struct (line 795) | func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base str...

FILE: vendor/github.com/golang/protobuf/proto/encode.go
  type RequiredNotSetError (line 54) | type RequiredNotSetError struct
    method Error (line 58) | func (e *RequiredNotSetError) Error() string {
  constant maxVarintBytes (line 75) | maxVarintBytes = 10
  function EncodeVarint (line 83) | func EncodeVarint(x uint64) []byte {
  method EncodeVarint (line 99) | func (p *Buffer) EncodeVarint(x uint64) error {
  function sizeVarint (line 108) | func sizeVarint(x uint64) (n int) {
  method EncodeFixed64 (line 122) | func (p *Buffer) EncodeFixed64(x uint64) error {
  function sizeFixed64 (line 135) | func sizeFixed64(x uint64) int {
  method EncodeFixed32 (line 142) | func (p *Buffer) EncodeFixed32(x uint64) error {
  function sizeFixed32 (line 151) | func sizeFixed32(x uint64) int {
  method EncodeZigzag64 (line 158) | func (p *Buffer) EncodeZigzag64(x uint64) error {
  function sizeZigzag64 (line 163) | func sizeZigzag64(x uint64) int {
  method EncodeZigzag32 (line 170) | func (p *Buffer) EncodeZigzag32(x uint64) error {
  function sizeZigzag32 (line 175) | func sizeZigzag32(x uint64) int {
  method EncodeRawBytes (line 182) | func (p *Buffer) EncodeRawBytes(b []byte) error {
  function sizeRawBytes (line 188) | func sizeRawBytes(b []byte) int {
  method EncodeStringBytes (line 195) | func (p *Buffer) EncodeStringBytes(s string) error {
  function sizeStringBytes (line 201) | func sizeStringBytes(s string) int {
  type Marshaler (line 207) | type Marshaler interface
  function Marshal (line 213) | func Marshal(pb Message) ([]byte, error) {
  method Marshal (line 234) | func (p *Buffer) Marshal(pb Message) error {
  function Size (line 261) | func Size(pb Message) (n int) {
  method enc_bool (line 287) | func (o *Buffer) enc_bool(p *Properties, base structPointer) error {
  method enc_proto3_bool (line 301) | func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error {
  function size_bool (line 311) | func size_bool(p *Properties, base structPointer) int {
  function size_proto3_bool (line 319) | func size_proto3_bool(p *Properties, base structPointer) int {
  method enc_int32 (line 328) | func (o *Buffer) enc_int32(p *Properties, base structPointer) error {
  method enc_proto3_int32 (line 339) | func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) err...
  function size_int32 (line 350) | func size_int32(p *Properties, base structPointer) (n int) {
  function size_proto3_int32 (line 361) | func size_proto3_int32(p *Properties, base structPointer) (n int) {
  method enc_uint32 (line 374) | func (o *Buffer) enc_uint32(p *Properties, base structPointer) error {
  method enc_proto3_uint32 (line 385) | func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) er...
  function size_uint32 (line 396) | func size_uint32(p *Properties, base structPointer) (n int) {
  function size_proto3_uint32 (line 407) | func size_proto3_uint32(p *Properties, base structPointer) (n int) {
  method enc_int64 (line 419) | func (o *Buffer) enc_int64(p *Properties, base structPointer) error {
  method enc_proto3_int64 (line 430) | func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) err...
  function size_int64 (line 441) | func size_int64(p *Properties, base structPointer) (n int) {
  function size_proto3_int64 (line 452) | func size_proto3_int64(p *Properties, base structPointer) (n int) {
  method enc_string (line 464) | func (o *Buffer) enc_string(p *Properties, base structPointer) error {
  method enc_proto3_string (line 475) | func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) er...
  function size_string (line 485) | func size_string(p *Properties, base structPointer) (n int) {
  function size_proto3_string (line 496) | func size_proto3_string(p *Properties, base structPointer) (n int) {
  function isNil (line 507) | func isNil(v reflect.Value) bool {
  method enc_struct_message (line 516) | func (o *Buffer) enc_struct_message(p *Properties, base structPointer) e...
  function size_struct_message (line 539) | func size_struct_message(p *Properties, base structPointer) int {
  method enc_struct_group (line 561) | func (o *Buffer) enc_struct_group(p *Properties, base structPointer) err...
  function size_struct_group (line 577) | func size_struct_group(p *Properties, base structPointer) (n int) {
  method enc_slice_bool (line 590) | func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error {
  function size_slice_bool (line 607) | func size_slice_bool(p *Properties, base structPointer) int {
  method enc_slice_packed_bool (line 617) | func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer...
  function size_slice_packed_bool (line 635) | func size_slice_packed_bool(p *Properties, base structPointer) (n int) {
  method enc_slice_byte (line 648) | func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error {
  method enc_proto3_slice_byte (line 658) | func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer...
  function size_slice_byte (line 668) | func size_slice_byte(p *Properties, base structPointer) (n int) {
  function size_proto3_slice_byte (line 678) | func size_proto3_slice_byte(p *Properties, base structPointer) (n int) {
  method enc_slice_int32 (line 689) | func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error {
  function size_slice_int32 (line 703) | func size_slice_int32(p *Properties, base structPointer) (n int) {
  method enc_slice_packed_int32 (line 718) | func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointe...
  function size_slice_packed_int32 (line 737) | func size_slice_packed_int32(p *Properties, base structPointer) (n int) {
  method enc_slice_uint32 (line 757) | func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) err...
  function size_slice_uint32 (line 771) | func size_slice_uint32(p *Properties, base structPointer) (n int) {
  method enc_slice_packed_uint32 (line 787) | func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPoint...
  function size_slice_packed_uint32 (line 805) | func size_slice_packed_uint32(p *Properties, base structPointer) (n int) {
  method enc_slice_int64 (line 823) | func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error {
  function size_slice_int64 (line 836) | func size_slice_int64(p *Properties, base structPointer) (n int) {
  method enc_slice_packed_int64 (line 850) | func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointe...
  function size_slice_packed_int64 (line 868) | func size_slice_packed_int64(p *Properties, base structPointer) (n int) {
  method enc_slice_slice_byte (line 886) | func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer)...
  function size_slice_slice_byte (line 899) | func size_slice_slice_byte(p *Properties, base structPointer) (n int) {
  method enc_slice_string (line 913) | func (o *Buffer) enc_slice_string(p *Properties, base structPointer) err...
  function size_slice_string (line 923) | func size_slice_string(p *Properties, base structPointer) (n int) {
  method enc_slice_struct_message (line 934) | func (o *Buffer) enc_slice_struct_message(p *Properties, base structPoin...
  function size_slice_struct_message (line 969) | func size_slice_struct_message(p *Properties, base structPointer) (n int) {
  method enc_slice_struct_group (line 996) | func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointe...
  function size_slice_struct_group (line 1023) | func size_slice_struct_group(p *Properties, base structPointer) (n int) {
  method enc_map (line 1041) | func (o *Buffer) enc_map(p *Properties, base structPointer) error {
  function size_map (line 1067) | func size_map(p *Properties, base structPointer) int {
  method enc_new_map (line 1073) | func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
  function size_new_map (line 1125) | func size_new_map(p *Properties, base structPointer) int {
  function mapEncodeScratch (line 1148) | func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Va...
  method enc_struct (line 1180) | func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) ...
  function size_struct (line 1215) | func size_struct(prop *StructProperties, base structPointer) (n int) {
  method enc_len_struct (line 1235) | func (o *Buffer) enc_len_struct(prop *StructProperties, base structPoint...
  method enc_len_thing (line 1240) | func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error {
  type errorState (line 1269) | type errorState struct
    method shouldContinue (line 1280) | func (s *errorState) shouldContinue(err error, prop *Properties) bool {

FILE: vendor/github.com/golang/protobuf/proto/equal.go
  function Equal (line 67) | func Equal(a, b Message) bool {
  function equalStruct (line 91) | func equalStruct(v1, v2 reflect.Value) bool {
  function equalAny (line 144) | func equalAny(v1, v2 reflect.Value) bool {
  function equalExtensions (line 207) | func equalExtensions(base reflect.Type, em1, em2 map[int32]Extension) bo...

FILE: vendor/github.com/golang/protobuf/proto/extensions.go
  type ExtensionRange (line 51) | type ExtensionRange struct
  type extendableProto (line 56) | type extendableProto interface
  type ExtensionDesc (line 66) | type ExtensionDesc struct
    method repeated (line 74) | func (ed *ExtensionDesc) repeated() bool {
  type Extension (line 80) | type Extension struct
  function SetRawExtension (line 95) | func SetRawExtension(base extendableProto, id int32, b []byte) {
  function isExtensionField (line 100) | func isExtensionField(pb extendableProto, field int32) bool {
  function checkExtensionTypes (line 110) | func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) e...
  type extPropKey (line 123) | type extPropKey struct
  function extensionProperties (line 135) | func extensionProperties(ed *ExtensionDesc) *Properties {
  function encodeExtensionMap (line 159) | func encodeExtensionMap(m map[int32]Extension) error {
  function sizeExtensionMap (line 187) | func sizeExtensionMap(m map[int32]Extension) (n int) {
  function HasExtension (line 212) | func HasExtension(pb extendableProto, extension *ExtensionDesc) bool {
  function ClearExtension (line 219) | func ClearExtension(pb extendableProto, extension *ExtensionDesc) {
  function GetExtension (line 226) | func GetExtension(pb extendableProto, extension *ExtensionDesc) (interfa...
  function defaultExtensionValue (line 266) | func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
  function decodeExtension (line 300) | func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, e...
  function GetExtensions (line 335) | func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interf...
  function SetExtension (line 355) | func SetExtension(pb extendableProto, extension *ExtensionDesc, value in...
  function RegisterExtension (line 382) | func RegisterExtension(desc *ExtensionDesc) {
  function RegisteredExtensions (line 398) | func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {

FILE: vendor/github.com/golang/protobuf/proto/lib.go
  type Message (line 219) | type Message interface
  type Stats (line 227) | type Stats struct
  constant collectStats (line 238) | collectStats = false
  function GetStats (line 243) | func GetStats() Stats { return stats }
  type Buffer (line 250) | type Buffer struct
    method Reset (line 273) | func (p *Buffer) Reset() {
    method SetBuf (line 280) | func (p *Buffer) SetBuf(s []byte) {
    method Bytes (line 286) | func (p *Buffer) Bytes() []byte { return p.buf }
    method DebugPrint (line 388) | func (p *Buffer) DebugPrint(s string, b []byte) {
  function NewBuffer (line 268) | func NewBuffer(e []byte) *Buffer {
  function Bool (line 294) | func Bool(v bool) *bool {
  function Int32 (line 300) | func Int32(v int32) *int32 {
  function Int (line 307) | func Int(v int) *int32 {
  function Int64 (line 315) | func Int64(v int64) *int64 {
  function Float32 (line 321) | func Float32(v float32) *float32 {
  function Float64 (line 327) | func Float64(v float64) *float64 {
  function Uint32 (line 333) | func Uint32(v uint32) *uint32 {
  function Uint64 (line 339) | func Uint64(v uint64) *uint64 {
  function String (line 345) | func String(v string) *string {
  function EnumName (line 351) | func EnumName(m map[int32]string, v int32) string {
  function UnmarshalJSONEnum (line 365) | func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string)...
  function SetDefaults (line 502) | func SetDefaults(pb Message) {
  function setDefaults (line 507) | func setDefaults(v reflect.Value, recur, zeros bool) {
  type defaultMessage (line 649) | type defaultMessage struct
  type scalarField (line 654) | type scalarField struct
  function buildDefaultMessage (line 661) | func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
  function fieldDefault (line 690) | func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, n...
  type mapKeys (line 790) | type mapKeys
    method Len (line 792) | func (s mapKeys) Len() int      { return len(s) }
    method Swap (line 793) | func (s mapKeys) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
    method Less (line 794) | func (s mapKeys) Less(i, j int) bool {

FILE: vendor/github.com/golang/protobuf/proto/message_set.go
  type _MessageSet_Item (line 69) | type _MessageSet_Item struct
  type MessageSet (line 74) | type MessageSet struct
    method find (line 89) | func (ms *MessageSet) find(pb Message) *_MessageSet_Item {
    method Has (line 103) | func (ms *MessageSet) Has(pb Message) bool {
    method Unmarshal (line 110) | func (ms *MessageSet) Unmarshal(pb Message) error {
    method Marshal (line 120) | func (ms *MessageSet) Marshal(pb Message) error {
    method Reset (line 144) | func (ms *MessageSet) Reset()         { *ms = MessageSet{} }
    method String (line 145) | func (ms *MessageSet) String() string { return CompactTextString(ms) }
    method ProtoMessage (line 146) | func (*MessageSet) ProtoMessage()     {}
  type messageTypeIder (line 85) | type messageTypeIder interface
  function skipVarint (line 150) | func skipVarint(buf []byte) []byte {
  function MarshalMessageSet (line 159) | func MarshalMessageSet(m map[int32]Extension) ([]byte, error) {
  function UnmarshalMessageSet (line 188) | func UnmarshalMessageSet(buf []byte, m map[int32]Extension) error {
  function MarshalMessageSetJSON (line 219) | func MarshalMessageSetJSON(m map[int32]Extension) ([]byte, error) {
  function UnmarshalMessageSetJSON (line 262) | func UnmarshalMessageSetJSON(buf []byte, m map[int32]Extension) error {
  type messageSetDesc (line 276) | type messageSetDesc struct
  function RegisterMessageSetType (line 282) | func RegisterMessageSetType(m Message, fieldNum int32, name string) {

FILE: vendor/github.com/golang/protobuf/proto/pointer_reflect.go
  type structPointer (line 46) | type structPointer struct
  function toStructPointer (line 52) | func toStructPointer(v reflect.Value) structPointer {
  function structPointer_IsNil (line 57) | func structPointer_IsNil(p structPointer) bool {
  function structPointer_Interface (line 62) | func structPointer_Interface(p structPointer, _ reflect.Type) interface{} {
  type field (line 69) | type field
    method IsValid (line 80) | func (f field) IsValid() bool { return f != nil }
  function toField (line 72) | func toField(f *reflect.StructField) field {
  function structPointer_field (line 83) | func structPointer_field(p structPointer, f field) reflect.Value {
  function structPointer_ifield (line 98) | func structPointer_ifield(p structPointer, f field) interface{} {
  function structPointer_Bytes (line 103) | func structPointer_Bytes(p structPointer, f field) *[]byte {
  function structPointer_BytesSlice (line 108) | func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
  function structPointer_Bool (line 113) | func structPointer_Bool(p structPointer, f field) **bool {
  function structPointer_BoolVal (line 118) | func structPointer_BoolVal(p structPointer, f field) *bool {
  function structPointer_BoolSlice (line 123) | func structPointer_BoolSlice(p structPointer, f field) *[]bool {
  function structPointer_String (line 128) | func structPointer_String(p structPointer, f field) **string {
  function structPointer_StringVal (line 133) | func structPointer_StringVal(p structPointer, f field) *string {
  function structPointer_StringSlice (line 138) | func structPointer_StringSlice(p structPointer, f field) *[]string {
  function structPointer_ExtMap (line 143) | func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
  function structPointer_Map (line 148) | func structPointer_Map(p structPointer, f field, typ reflect.Type) refle...
  function structPointer_SetStructPointer (line 153) | func structPointer_SetStructPointer(p structPointer, f field, q structPo...
  function structPointer_GetStructPointer (line 158) | func structPointer_GetStructPointer(p structPointer, f field) structPoin...
  function structPointer_StructPointerSlice (line 163) | func structPointer_StructPointerSlice(p structPointer, f field) structPo...
  type structPointerSlice (line 169) | type structPointerSlice struct
    method Len (line 173) | func (p structPointerSlice) Len() int                  { return p.v.Le...
    method Index (line 174) | func (p structPointerSlice) Index(i int) structPointer { return struct...
    method Append (line 175) | func (p structPointerSlice) Append(q structPointer) {
  type word32 (line 190) | type word32 struct
  function word32_IsNil (line 195) | func word32_IsNil(p word32) bool {
  function word32_Set (line 200) | func word32_Set(p word32, o *Buffer, x uint32) {
  function word32_Get (line 235) | func word32_Get(p word32) uint32 {
  function structPointer_Word32 (line 249) | func structPointer_Word32(p structPointer, f field) word32 {
  type word32Val (line 255) | type word32Val struct
  function word32Val_Set (line 260) | func word32Val_Set(p word32Val, x uint32) {
  function word32Val_Get (line 278) | func word32Val_Get(p word32Val) uint32 {
  function structPointer_Word32Val (line 292) | func structPointer_Word32Val(p structPointer, f field) word32Val {
  type word32Slice (line 298) | type word32Slice struct
    method Append (line 302) | func (p word32Slice) Append(x uint32) {
    method Len (line 321) | func (p word32Slice) Len() int {
    method Index (line 325) | func (p word32Slice) Index(i int) uint32 {
  function structPointer_Word32Slice (line 339) | func structPointer_Word32Slice(p structPointer, f field) word32Slice {
  type word64 (line 344) | type word64 struct
  function word64_Set (line 348) | func word64_Set(p word64, o *Buffer, x uint64) {
  function word64_IsNil (line 379) | func word64_IsNil(p word64) bool {
  function word64_Get (line 383) | func word64_Get(p word64) uint64 {
  function structPointer_Word64 (line 396) | func structPointer_Word64(p structPointer, f field) word64 {
  type word64Val (line 401) | type word64Val struct
  function word64Val_Set (line 405) | func word64Val_Set(p word64Val, o *Buffer, x uint64) {
  function word64Val_Get (line 420) | func word64Val_Get(p word64Val) uint64 {
  function structPointer_Word64Val (line 433) | func structPointer_Word64Val(p structPointer, f field) word64Val {
  type word64Slice (line 437) | type word64Slice struct
    method Append (line 441) | func (p word64Slice) Append(x uint64) {
    method Len (line 460) | func (p word64Slice) Len() int {
    method Index (line 464) | func (p word64Slice) Index(i int) uint64 {
  function structPointer_Word64Slice (line 477) | func structPointer_Word64Slice(p structPointer, f field) word64Slice {

FILE: vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
  type structPointer (line 53) | type structPointer
  function toStructPointer (line 56) | func toStructPointer(v reflect.Value) structPointer {
  function structPointer_IsNil (line 61) | func structPointer_IsNil(p structPointer) bool {
  function structPointer_Interface (line 67) | func structPointer_Interface(p structPointer, t reflect.Type) interface{} {
  type field (line 73) | type field
    method IsValid (line 84) | func (f field) IsValid() bool {
  function toField (line 76) | func toField(f *reflect.StructField) field {
  constant invalidField (line 81) | invalidField = ^field(0)
  function structPointer_Bytes (line 89) | func structPointer_Bytes(p structPointer, f field) *[]byte {
  function structPointer_BytesSlice (line 94) | func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
  function structPointer_Bool (line 99) | func structPointer_Bool(p structPointer, f field) **bool {
  function structPointer_BoolVal (line 104) | func structPointer_BoolVal(p structPointer, f field) *bool {
  function structPointer_BoolSlice (line 109) | func structPointer_BoolSlice(p structPointer, f field) *[]bool {
  function structPointer_String (line 114) | func structPointer_String(p structPointer, f field) **string {
  function structPointer_StringVal (line 119) | func structPointer_StringVal(p structPointer, f field) *string {
  function structPointer_StringSlice (line 124) | func structPointer_StringSlice(p structPointer, f field) *[]string {
  function structPointer_ExtMap (line 129) | func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
  function structPointer_Map (line 134) | func structPointer_Map(p structPointer, f field, typ reflect.Type) refle...
  function structPointer_SetStructPointer (line 139) | func structPointer_SetStructPointer(p structPointer, f field, q structPo...
  function structPointer_GetStructPointer (line 144) | func structPointer_GetStructPointer(p structPointer, f field) structPoin...
  function structPointer_StructPointerSlice (line 149) | func structPointer_StructPointerSlice(p structPointer, f field) *structP...
  type structPointerSlice (line 154) | type structPointerSlice
    method Len (line 156) | func (v *structPointerSlice) Len() int                  { return len(*...
    method Index (line 157) | func (v *structPointerSlice) Index(i int) structPointer { return (*v)[...
    method Append (line 158) | func (v *structPointerSlice) Append(p structPointer)    { *v = append(...
  type word32 (line 161) | type word32
  function word32_IsNil (line 164) | func word32_IsNil(p word32) bool {
  function word32_Set (line 169) | func word32_Set(p word32, o *Buffer, x uint32) {
  function word32_Get (line 179) | func word32_Get(p word32) uint32 {
  function structPointer_Word32 (line 184) | func structPointer_Word32(p structPointer, f field) word32 {
  type word32Val (line 189) | type word32Val
  function word32Val_Set (line 192) | func word32Val_Set(p word32Val, x uint32) {
  function word32Val_Get (line 197) | func word32Val_Get(p word32Val) uint32 {
  function structPointer_Word32Val (line 202) | func structPointer_Word32Val(p structPointer, f field) word32Val {
  type word32Slice (line 207) | type word32Slice
    method Append (line 209) | func (v *word32Slice) Append(x uint32)    { *v = append(*v, x) }
    method Len (line 210) | func (v *word32Slice) Len() int           { return len(*v) }
    method Index (line 211) | func (v *word32Slice) Index(i int) uint32 { return (*v)[i] }
  function structPointer_Word32Slice (line 214) | func structPointer_Word32Slice(p structPointer, f field) *word32Slice {
  type word64 (line 219) | type word64
  function word64_Set (line 221) | func word64_Set(p word64, o *Buffer, x uint64) {
  function word64_IsNil (line 230) | func word64_IsNil(p word64) bool {
  function word64_Get (line 234) | func word64_Get(p word64) uint64 {
  function structPointer_Word64 (line 238) | func structPointer_Word64(p structPointer, f field) word64 {
  type word64Val (line 243) | type word64Val
  function word64Val_Set (line 245) | func word64Val_Set(p word64Val, o *Buffer, x uint64) {
  function word64Val_Get (line 249) | func word64Val_Get(p word64Val) uint64 {
  function structPointer_Word64Val (line 253) | func structPointer_Word64Val(p structPointer, f field) word64Val {
  type word64Slice (line 258) | type word64Slice
    method Append (line 260) | func (v *word64Slice) Append(x uint64)    { *v = append(*v, x) }
    method Len (line 261) | func (v *word64Slice) Len() int           { return len(*v) }
    method Index (line 262) | func (v *word64Slice) Index(i int) uint64 { return (*v)[i] }
  function structPointer_Word64Slice (line 264) | func structPointer_Word64Slice(p structPointer, f field) *word64Slice {

FILE: vendor/github.com/golang/protobuf/proto/properties.go
  constant debug (line 48) | debug bool = false
  constant WireVarint (line 52) | WireVarint     = 0
  constant WireFixed64 (line 53) | WireFixed64    = 1
  constant WireBytes (line 54) | WireBytes      = 2
  constant WireStartGroup (line 55) | WireStartGroup = 3
  constant WireEndGroup (line 56) | WireEndGroup   = 4
  constant WireFixed32 (line 57) | WireFixed32    = 5
  constant startSize (line 60) | startSize = 10
  type encoder (line 65) | type encoder
  type valueEncoder (line 68) | type valueEncoder
  type sizer (line 73) | type sizer
  type valueSizer (line 77) | type valueSizer
  type decoder (line 82) | type decoder
  type valueDecoder (line 85) | type valueDecoder
  type tagMap (line 90) | type tagMap struct
    method get (line 99) | func (p *tagMap) get(t int) (int, bool) {
    method put (line 111) | func (p *tagMap) put(t int, fi int) {
  constant tagMapFastLimit (line 97) | tagMapFastLimit = 1024
  type StructProperties (line 127) | type StructProperties struct
    method Len (line 140) | func (sp *StructProperties) Len() int { return len(sp.order) }
    method Less (line 141) | func (sp *StructProperties) Less(i, j int) bool {
    method Swap (line 144) | func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] ...
  type Properties (line 147) | type Properties struct
    method String (line 189) | func (p *Properties) String() string {
    method Parse (line 221) | func (p *Properties) Parse(s string) {
    method setEncAndDec (line 306) | func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructF...
    method Init (line 584) | func (p *Properties) Init(typ reflect.Type, name, tag string, f *refle...
    method init (line 588) | func (p *Properties) init(typ reflect.Type, name, tag string, f *refle...
  function logNoSliceEnc (line 299) | func logNoSliceEnc(t1, t2 reflect.Type) {
  function isMarshaler (line 562) | func isMarshaler(t reflect.Type) bool {
  function isUnmarshaler (line 573) | func isUnmarshaler(t reflect.Type) bool {
  function GetProperties (line 609) | func GetProperties(t reflect.Type) *StructProperties {
  function getPropertiesLocked (line 633) | func getPropertiesLocked(t reflect.Type) *StructProperties {
  function propByIndex (line 707) | func propByIndex(t reflect.Type, x []int) *Properties {
  function getbase (line 717) | func getbase(pb Message) (t reflect.Type, b structPointer, err error) {
  function RegisterEnum (line 737) | func RegisterEnum(typeName string, unusedNameMap map[int32]string, value...

FILE: vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go
  type Message_Humour (line 24) | type Message_Humour
    method String (line 46) | func (x Message_Humour) String() string {
  constant Message_UNKNOWN (line 27) | Message_UNKNOWN     Message_Humour = 0
  constant Message_PUNS (line 28) | Message_PUNS        Message_Humour = 1
  constant Message_SLAPSTICK (line 29) | Message_SLAPSTICK   Message_Humour = 2
  constant Message_BILL_BAILEY (line 30) | Message_BILL_BAILEY Message_Humour = 3
  type Message (line 50) | type Message struct
    method Reset (line 65) | func (m *Message) Reset()         { *m = Message{} }
    method String (line 66) | func (m *Message) String() string { return proto.CompactTextString(m) }
    method ProtoMessage (line 67) | func (*Message) ProtoMessage()    {}
    method GetNested (line 69) | func (m *Message) GetNested() *Nested {
    method GetTerrain (line 76) | func (m *Message) GetTerrain() map[string]*Nested {
    method GetProto2Field (line 83) | func (m *Message) GetProto2Field() *testdata.SubDefaults {
    method GetProto2Value (line 90) | func (m *Message) GetProto2Value() map[string]*testdata.SubDefaults {
  type Nested (line 97) | type Nested struct
    method Reset (line 101) | func (m *Nested) Reset()         { *m = Nested{} }
    method String (line 102) | func (m *Nested) String() string { return proto.CompactTextString(m) }
    method ProtoMessage (line 103) | func (*Nested) ProtoMessage()    {}
  type MessageWithMap (line 105) | type MessageWithMap struct
    method Reset (line 109) | func (m *MessageWithMap) Reset()         { *m = MessageWithMap{} }
    method String (line 110) | func (m *MessageWithMap) String() string { return proto.CompactTextStr...
    method ProtoMessage (line 111) | func (*MessageWithMap) ProtoMessage()    {}
    method GetByteMapping (line 113) | func (m *MessageWithMap) GetByteMapping() map[bool][]byte {
  function init (line 120) | func init() {

FILE: vendor/github.com/golang/protobuf/proto/text.go
  type writer (line 65) | type writer interface
  type textWriter (line 71) | type textWriter struct
    method WriteString (line 78) | func (w *textWriter) WriteString(s string) (n int, err error) {
    method Write (line 92) | func (w *textWriter) Write(p []byte) (n int, err error) {
    method WriteByte (line 141) | func (w *textWriter) WriteByte(c byte) error {
    method indent (line 153) | func (w *textWriter) indent() { w.ind++ }
    method unindent (line 155) | func (w *textWriter) unindent() {
    method writeIndent (line 713) | func (w *textWriter) writeIndent() {
  function writeName (line 163) | func writeName(w *textWriter, props *Properties) error {
  type raw (line 178) | type raw interface
  function writeStruct (line 182) | func writeStruct(w *textWriter, sv reflect.Value) error {
  function writeRaw (line 382) | func writeRaw(w *textWriter, b []byte) error {
  function writeAny (line 403) | func writeAny(w *textWriter, v reflect.Value, props *Properties) error {
  function isprint (line 475) | func isprint(c byte) bool {
  function writeString (line 484) | func writeString(w *textWriter, s string) error {
  function writeMessageSet (line 520) | func writeMessageSet(w *textWriter, ms *MessageSet) error {
  function writeUnknownStruct (line 558) | func writeUnknownStruct(w *textWriter, data []byte) (err error) {
  function writeUnknownInt (line 625) | func writeUnknownInt(w *textWriter, x uint64, err error) error {
  type int32Slice (line 634) | type int32Slice
    method Len (line 636) | func (s int32Slice) Len() int           { return len(s) }
    method Less (line 637) | func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
    method Swap (line 638) | func (s int32Slice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
  function writeExtensions (line 642) | func writeExtensions(w *textWriter, pv reflect.Value) error {
  function writeExtension (line 695) | func writeExtension(w *textWriter, name string, pb interface{}) error {
  function marshalText (line 729) | func marshalText(w io.Writer, pb Message, compact bool) error {
  function MarshalText (line 773) | func MarshalText(w io.Writer, pb Message) error {
  function MarshalTextString (line 778) | func MarshalTextString(pb Message) string {
  function CompactText (line 785) | func CompactText(w io.Writer, pb Message) error { return marshalText(w, ...
  function CompactTextString (line 788) | func CompactTextString(pb Message) string {

FILE: vendor/github.com/golang/protobuf/proto/text_parser.go
  type ParseError (line 47) | type ParseError struct
    method Error (line 53) | func (p *ParseError) Error() string {
  type token (line 61) | type token struct
    method String (line 69) | func (t *token) String() string {
  type textParser (line 76) | type textParser struct
    method errorf (line 92) | func (p *textParser) errorf(format string, a ...interface{}) *ParseErr...
    method skipWhitespace (line 122) | func (p *textParser) skipWhitespace() {
    method advance (line 146) | func (p *textParser) advance() {
    method back (line 325) | func (p *textParser) back() { p.backed = true }
    method next (line 328) | func (p *textParser) next() *token {
    method consumeToken (line 358) | func (p *textParser) consumeToken(s string) error {
    method missingRequiredFieldError (line 371) | func (p *textParser) missingRequiredFieldError(sv reflect.Value) *Requ...
    method checkForColon (line 399) | func (p *textParser) checkForColon(props *Properties, typ reflect.Type...
    method readStruct (line 439) | func (p *textParser) readStruct(sv reflect.Value, terminator string) e...
    method consumeOptionalSeparator (line 628) | func (p *textParser) consumeOptionalSeparator() error {
    method readAny (line 639) | func (p *textParser) readAny(v reflect.Value, props *Properties) error {
  function newTextParser (line 84) | func newTextParser(s string) *textParser {
  function isIdentOrNumberChar (line 100) | func isIdentOrNumberChar(c byte) bool {
  function isWhitespace (line 114) | func isWhitespace(c byte) bool {
  function unquoteC (line 201) | func unquoteC(s string, quote rune) (string, error) {
  function unescape (line 244) | func unescape(s string) (ch string, tail string, err error) {
  function unhex (line 311) | func unhex(b byte) (v byte, ok bool) {
  function structFieldByName (line 388) | func structFieldByName(st reflect.Type, name string) (int, *Properties, ...
  function UnmarshalText (line 761) | func UnmarshalText(s string, pb Message) error {

FILE: vendor/github.com/gorilla/context/context.go
  function Set (line 20) | func Set(r *http.Request, key, val interface{}) {
  function Get (line 31) | func Get(r *http.Request, key interface{}) interface{} {
  function GetOk (line 43) | func GetOk(r *http.Request, key interface{}) (interface{}, bool) {
  function GetAll (line 55) | func GetAll(r *http.Request) map[interface{}]interface{} {
  function GetAllOk (line 71) | func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) {
  function Delete (line 83) | func Delete(r *http.Request, key interface{}) {
  function Clear (line 95) | func Clear(r *http.Request) {
  function clear (line 102) | func clear(r *http.Request) {
  function Purge (line 116) | func Purge(maxAge int) int {
  function ClearHandler (line 138) | func ClearHandler(h http.Handler) http.Handler {

FILE: vendor/github.com/gorilla/mux/mux.go
  function NewRouter (line 16) | func NewRouter() *Router {
  type Router (line 38) | type Router struct
    method Match (line 54) | func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
    method ServeHTTP (line 67) | func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    method Get (line 102) | func (r *Router) Get(name string) *Route {
    method GetRoute (line 108) | func (r *Router) GetRoute(name string) *Route {
    method StrictSlash (line 126) | func (r *Router) StrictSlash(value bool) *Router {
    method getNamedRoutes (line 136) | func (r *Router) getNamedRoutes() map[string]*Route {
    method getRegexpGroup (line 148) | func (r *Router) getRegexpGroup() *routeRegexpGroup {
    method buildVars (line 155) | func (r *Router) buildVars(m map[string]string) map[string]string {
    method NewRoute (line 167) | func (r *Router) NewRoute() *Route {
    method Handle (line 175) | func (r *Router) Handle(path string, handler http.Handler) *Route {
    method HandleFunc (line 181) | func (r *Router) HandleFunc(path string, f func(http.ResponseWriter,
    method Headers (line 188) | func (r *Router) Headers(pairs ...string) *Route {
    method Host (line 194) | func (r *Router) Host(tpl string) *Route {
    method MatcherFunc (line 200) | func (r *Router) MatcherFunc(f MatcherFunc) *Route {
    method Methods (line 206) | func (r *Router) Methods(methods ...string) *Route {
    method Path (line 212) | func (r *Router) Path(tpl string) *Route {
    method PathPrefix (line 218) | func (r *Router) PathPrefix(tpl string) *Route {
    method Queries (line 224) | func (r *Router) Queries(pairs ...string) *Route {
    method Schemes (line 230) | func (r *Router) Schemes(schemes ...string) *Route {
    method BuildVarsFunc (line 236) | func (r *Router) BuildVarsFunc(f BuildVarsFunc) *Route {
  type RouteMatch (line 245) | type RouteMatch struct
  type contextKey (line 251) | type contextKey
  constant varsKey (line 254) | varsKey contextKey = iota
  constant routeKey (line 255) | routeKey
  function Vars (line 259) | func Vars(r *http.Request) map[string]string {
  function CurrentRoute (line 267) | func CurrentRoute(r *http.Request) *Route {
  function setVars (line 274) | func setVars(r *http.Request, val interface{}) {
  function setCurrentRoute (line 278) | func setCurrentRoute(r *http.Request, val interface{}) {
  function cleanPath (line 288) | func cleanPath(p string) string {
  function uniqueVars (line 305) | func uniqueVars(s1, s2 []string) error {
  function mapFromPairs (line 317) | func mapFromPairs(pairs ...string) (map[string]string, error) {
  function matchInArray (line 331) | func matchInArray(arr []string, value string) bool {
  function matchMap (line 341) | func matchMap(toCheck map[string]string, toMatch map[string][]string,

FILE: vendor/github.com/gorilla/mux/regexp.go
  function newRouteRegexp (line 26) | func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, stri...
  type routeRegexp (line 121) | type routeRegexp struct
    method Match (line 141) | func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool {
    method url (line 153) | func (r *routeRegexp) url(values map[string]string) (string, error) {
  function braceIndices (line 180) | func braceIndices(s string) ([]int, error) {
  type routeRegexpGroup (line 208) | type routeRegexpGroup struct
    method setMatch (line 215) | func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, ...
  function getHost (line 261) | func getHost(r *http.Request) string {

FILE: vendor/github.com/gorilla/mux/route.go
  type Route (line 16) | type Route struct
    method Match (line 39) | func (r *Route) Match(req *http.Request, match *RouteMatch) bool {
    method GetError (line 71) | func (r *Route) GetError() error {
    method BuildOnly (line 76) | func (r *Route) BuildOnly() *Route {
    method Handler (line 84) | func (r *Route) Handler(handler http.Handler) *Route {
    method HandlerFunc (line 92) | func (r *Route) HandlerFunc(f func(http.ResponseWriter, *http.Request)...
    method GetHandler (line 97) | func (r *Route) GetHandler() http.Handler {
    method Name (line 105) | func (r *Route) Name(name string) *Route {
    method GetName (line 118) | func (r *Route) GetName() string {
    method addMatcher (line 132) | func (r *Route) addMatcher(m matcher) *Route {
    method addRegexpMatcher (line 140) | func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, m...
    method Headers (line 204) | func (r *Route) Headers(pairs ...string) *Route {
    method Host (line 232) | func (r *Route) Host(tpl string) *Route {
    method MatcherFunc (line 247) | func (r *Route) MatcherFunc(f MatcherFunc) *Route {
    method Methods (line 263) | func (r *Route) Methods(methods ...string) *Route {
    method Path (line 291) | func (r *Route) Path(tpl string) *Route {
    method PathPrefix (line 307) | func (r *Route) PathPrefix(tpl string) *Route {
    method Queries (line 331) | func (r *Route) Queries(pairs ...string) *Route {
    method Schemes (line 358) | func (r *Route) Schemes(schemes ...string) *Route {
    method BuildVarsFunc (line 373) | func (r *Route) BuildVarsFunc(f BuildVarsFunc) *Route {
    method Subrouter (line 392) | func (r *Route) Subrouter() *Router {
    method URL (line 433) | func (r *Route) URL(pairs ...string) (*url.URL, error) {
    method URLHost (line 467) | func (r *Route) URLHost(pairs ...string) (*url.URL, error) {
    method URLPath (line 491) | func (r *Route) URLPath(pairs ...string) (*url.URL, error) {
    method prepareVars (line 513) | func (r *Route) prepareVars(pairs ...string) (map[string]string, error) {
    method buildVars (line 521) | func (r *Route) buildVars(m map[string]string) map[string]string {
    method getNamedRoutes (line 543) | func (r *Route) getNamedRoutes() map[string]*Route {
    method getRegexpGroup (line 552) | func (r *Route) getRegexpGroup() *routeRegexpGroup {
  type matcher (line 127) | type matcher interface
  type headerMatcher (line 188) | type headerMatcher
    method Match (line 190) | func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool {
  type MatcherFunc (line 240) | type MatcherFunc
    method Match (line 242) | func (m MatcherFunc) Match(r *http.Request, match *RouteMatch) bool {
  type methodMatcher (line 254) | type methodMatcher
    method Match (line 256) | func (m methodMatcher) Match(r *http.Request, match *RouteMatch) bool {
  type schemeMatcher (line 350) | type schemeMatcher
    method Match (line 352) | func (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool {
  type BuildVarsFunc (line 369) | type BuildVarsFunc
  type parentRoute (line 536) | type parentRoute interface

FILE: vendor/github.com/mitchellh/goamz/aws/attempt.go
  type AttemptStrategy (line 10) | type AttemptStrategy struct
    method Start (line 25) | func (s AttemptStrategy) Start() *Attempt {
  type Attempt (line 16) | type Attempt struct
    method Next (line 37) | func (a *Attempt) Next() bool {
    method nextSleep (line 53) | func (a *Attempt) nextSleep(now time.Time) time.Duration {
    method HasNext (line 64) | func (a *Attempt) HasNext() bool {

FILE: vendor/github.com/mitchellh/goamz/aws/aws.go
  type Region (line 25) | type Region struct
  type Auth (line 243) | type Auth struct
  function init (line 250) | func init() {
  type credentials (line 258) | type credentials struct
  function GetMetaData (line 271) | func GetMetaData(path string) (contents []byte, err error) {
  function getInstanceCredentials (line 292) | func getInstanceCredentials() (cred credentials, err error) {
  function GetAuth (line 313) | func GetAuth(accessKey string, secretKey string) (auth Auth, err error) {
  function SharedAuth (line 349) | func SharedAuth() (auth Auth, err error) {
  function EnvAuth (line 394) | func EnvAuth() (auth Auth, err error) {
  function Encode (line 418) | func Encode(s string) string {

FILE: vendor/github.com/mitchellh/goamz/aws/client.go
  type RetryableFunc (line 10) | type RetryableFunc
  type WaitFunc (line 11) | type WaitFunc
  type DeadlineFunc (line 12) | type DeadlineFunc
  type ResilientTransport (line 14) | type ResilientTransport struct
    method RoundTrip (line 69) | func (t *ResilientTransport) RoundTrip(req *http.Request) (*http.Respo...
    method tries (line 77) | func (t *ResilientTransport) tries(req *http.Request) (res *http.Respo...
  function NewClient (line 36) | func NewClient(rt *ResilientTransport) *http.Client {
  function ExpBackoff (line 95) | func ExpBackoff(try int) {
  function LinearBackoff (line 100) | func LinearBackoff(try int) {
  function awsRetry (line 107) | func awsRetry(req *http.Request, res *http.Response, err error) bool {

FILE: vendor/github.com/mitchellh/goamz/s3/multi.go
  type Multi (line 22) | type Multi struct
    method PutPart (line 144) | func (m *Multi) PutPart(n int, r io.ReadSeeker) (Part, error) {
    method putPart (line 152) | func (m *Multi) putPart(n int, r io.ReadSeeker, partSize int64, md5b64...
    method ListParts (line 235) | func (m *Multi) ListParts() ([]Part, error) {
    method PutAll (line 278) | func (m *Multi) PutAll(r ReaderAtSeeker, partSize int64) ([]Part, erro...
    method Complete (line 346) | func (m *Multi) Complete(parts []Part) error {
    method Abort (line 391) | func (m *Multi) Abort() error {
  type listMultiResp (line 31) | type listMultiResp struct
  method ListMulti (line 51) | func (b *Bucket) ListMulti(prefix, delim string) (multis []*Multi, prefi...
  method Multi (line 91) | func (b *Bucket) Multi(key, contType string, perm ACL) (*Multi, error) {
  method InitMulti (line 108) | func (b *Bucket) InitMulti(key string, contType string, perm ACL) (*Mult...
  function seekerInfo (line 194) | func seekerInfo(r io.ReadSeeker) (size int64, md5hex string, md5b64 stri...
  type Part (line 210) | type Part struct
  type partSlice (line 216) | type partSlice
    method Len (line 218) | func (s partSlice) Len() int           { return len(s) }
    method Less (line 219) | func (s partSlice) Less(i, j int) bool { return s[i].N < s[j].N }
    method Swap (line 220) | func (s partSlice) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
  type listPartsResp (line 222) | type listPartsResp struct
  type ReaderAtSeeker (line 267) | type ReaderAtSeeker interface
  type completeUpload (line 326) | type completeUpload struct
  type completePart (line 331) | type completePart struct
  type completeParts (line 336) | type completeParts
    method Len (line 338) | func (p completeParts) Len() int           { return len(p) }
    method Less (line 339) | func (p completeParts) Less(i, j int) bool { return p[i].PartNumber < ...
    method Swap (line 340) | func (p completeParts) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

FILE: vendor/github.com/mitchellh/goamz/s3/s3.go
  constant debug (line 32) | debug = false
  type S3 (line 35) | type S3 struct
    method Bucket (line 73) | func (s3 *S3) Bucket(name string) *Bucket {
    method locationConstraint (line 88) | func (s3 *S3) locationConstraint() io.Reader {
    method ListBuckets (line 115) | func (s3 *S3) ListBuckets() (result *ListBucketsResp, err error) {
    method query (line 710) | func (s3 *S3) query(req *request, resp interface{}) error {
    method prepare (line 723) | func (s3 *S3) prepare(req *request) error {
    method run (line 779) | func (s3 *S3) run(req *request, resp interface{}) (*http.Response, err...
  type Bucket (line 44) | type Bucket struct
    method PutBucket (line 139) | func (b *Bucket) PutBucket(perm ACL) error {
    method DelBucket (line 157) | func (b *Bucket) DelBucket() (err error) {
    method Get (line 175) | func (b *Bucket) Get(path string) (data []byte, err error) {
    method GetReader (line 188) | func (b *Bucket) GetReader(path string) (rc io.ReadCloser, err error) {
    method GetResponse (line 199) | func (b *Bucket) GetResponse(path string) (*http.Response, error) {
    method GetTorrentReader (line 205) | func (b *Bucket) GetTorrentReader(path string) (io.ReadCloser, error) {
    method GetTorrent (line 215) | func (b *Bucket) GetTorrent(path string) ([]byte, error) {
    method getResponseParams (line 225) | func (b *Bucket) getResponseParams(path string, params url.Values) (*h...
    method Head (line 248) | func (b *Bucket) Head(path string) (*http.Response, error) {
    method Put (line 274) | func (b *Bucket) Put(path string, data []byte, contType string, perm A...
    method PutHeader (line 283) | func (b *Bucket) PutHeader(path string, data []byte, customHeaders map...
    method PutReader (line 290) | func (b *Bucket) PutReader(path string, r io.Reader, length int64, con...
    method PutReaderHeader (line 310) | func (b *Bucket) PutReaderHeader(path string, r io.Reader, length int6...
    method Copy (line 336) | func (b *Bucket) Copy(oldPath, newPath string, perm ACL) error {
    method Del (line 372) | func (b *Bucket) Del(path string) error {
    method MultiDel (line 401) | func (b *Bucket) MultiDel(paths []string) error {
    method List (line 509) | func (b *Bucket) List(prefix, delim, marker string, max int) (result *...
    method GetBucketContents (line 536) | func (b *Bucket) GetBucketContents() (*map[string]Key, error) {
    method GetKey (line 569) | func (b *Bucket) GetKey(path string) (*Key, error) {
    method URL (line 606) | func (b *Bucket) URL(path string) string {
    method SignedURL (line 625) | func (b *Bucket) SignedURL(path string, expires time.Time) string {
  type Owner (line 50) | type Owner struct
  function New (line 62) | func New(auth aws.Auth, region aws.Region) *S3 {
  type ACL (line 96) | type ACL
  constant Private (line 99) | Private           = ACL("private")
  constant PublicRead (line 100) | PublicRead        = ACL("public-read")
  constant PublicReadWrite (line 101) | PublicReadWrite   = ACL("public-read-write")
  constant AuthenticatedRead (line 102) | AuthenticatedRead = ACL("authenticated-read")
  constant BucketOwnerRead (line 103) | BucketOwnerRead   = ACL("bucket-owner-read")
  constant BucketOwnerFull (line 104) | BucketOwnerFull   = ACL("bucket-owner-full-control")
  type ListBucketsResp (line 108) | type ListBucketsResp struct
  type Object (line 381) | type Object struct
  type MultiObjectDeleteBody (line 385) | type MultiObjectDeleteBody struct
  function base64md5 (line 391) | func base64md5(data []byte) string {
  type ListResp (line 425) | type ListResp struct
  type Key (line 442) | type Key struct
  type request (line 642) | type request struct
    method url (line 692) | func (req *request) url(full bool) (*url.URL, error) {
  function amazonShouldEscape (line 655) | func amazonShouldEscape(c byte) bool {
  function amazonEscape (line 661) | func amazonEscape(s string) string {
  type Error (line 826) | type Error struct
    method Error (line 835) | func (e *Error) Error() string {
  function buildError (line 839) | func buildError(r *http.Response) error {
  function shouldRetry (line 865) | func shouldRetry(err error) bool {
  function hasCode (line 890) | func hasCode(err error, code string) bool {

FILE: vendor/github.com/mitchellh/goamz/s3/s3test/server.go
  constant debug (line 24) | debug = false
  type s3Error (line 26) | type s3Error struct
  type action (line 36) | type action struct
  type Config (line 46) | type Config struct
    method send409Conflict (line 55) | func (c *Config) send409Conflict() bool {
  type Server (line 64) | type Server struct
    method Quit (line 116) | func (srv *Server) Quit() {
    method URL (line 121) | func (srv *Server) URL() string {
    method serveHTTP (line 134) | func (srv *Server) serveHTTP(w http.ResponseWriter, req *http.Request) {
    method resourceForURL (line 228) | func (srv *Server) resourceForURL(u *url.URL) (r resource) {
  type bucket (line 73) | type bucket struct
  type object (line 80) | type object struct
    method s3Key (line 421) | func (obj *object) s3Key() s3.Key {
  type resource (line 91) | type resource interface
  function NewServer (line 98) | func NewServer(config *Config) (*Server, error) {
  function fatalf (line 125) | func fatalf(code int, codeStr string, errf string, a ...interface{}) {
  function xmlMarshal (line 196) | func xmlMarshal(w io.Writer, x interface{}) {
  type nullResource (line 279) | type nullResource struct
    method put (line 286) | func (nullResource) put(a *action) interface{}    { return notAllowed() }
    method get (line 287) | func (nullResource) get(a *action) interface{}    { return notAllowed() }
    method post (line 288) | func (nullResource) post(a *action) interface{}   { return notAllowed() }
    method delete (line 289) | func (nullResource) delete(a *action) interface{} { return notAllowed() }
  function notAllowed (line 281) | func notAllowed() interface{} {
  constant timeFormat (line 291) | timeFormat = "2006-01-02T15:04:05.000Z07:00"
  type serviceResource (line 293) | type serviceResource struct
    method put (line 297) | func (serviceResource) put(a *action) interface{}    { return notAllow...
    method post (line 298) | func (serviceResource) post(a *action) interface{}   { return notAllow...
    method delete (line 299) | func (serviceResource) delete(a *action) interface{} { return notAllow...
    method get (line 303) | func (r serviceResource) get(a *action) interface{} {
  type bucketResource (line 324) | type bucketResource struct
    method get (line 331) | func (r bucketResource) get(a *action) interface{} {
    method delete (line 433) | func (r bucketResource) delete(a *action) interface{} {
    method put (line 447) | func (r bucketResource) put(a *action) interface{} {
    method post (line 472) | func (bucketResource) post(a *action) interface{} {
  type orderedObjects (line 409) | type orderedObjects
    method Len (line 411) | func (s orderedObjects) Len() int {
    method Swap (line 414) | func (s orderedObjects) Swap(i, j int) {
    method Less (line 417) | func (s orderedObjects) Less(i, j int) bool {
  function validBucketName (line 493) | func validBucketName(name string) bool {
  type objectResource (line 523) | type objectResource struct
    method get (line 532) | func (objr objectResource) get(a *action) interface{} {
    method put (line 586) | func (objr objectResource) put(a *action) interface{} {
    method delete (line 637) | func (objr objectResource) delete(a *action) interface{} {
    method post (line 642) | func (objr objectResource) post(a *action) interface{} {
  type CreateBucketConfiguration (line 647) | type CreateBucketConfiguration struct
  function locationConstraint (line 653) | func locationConstraint(a *action) string {

FILE: vendor/github.com/mitchellh/goamz/s3/sign.go
  function sign (line 42) | func sign(auth aws.Auth, method, canonicalPath string, params, headers m...

FILE: vendor/github.com/trustmaster/go-aspell/aspell.go
  type Speller (line 17) | type Speller struct
    method Config (line 91) | func (s Speller) Config(name string) string {
    method Check (line 103) | func (s Speller) Check(word string) bool {
    method Delete (line 111) | func (s Speller) Delete() {
    method Suggest (line 142) | func (s Speller) Suggest(word string) []string {
    method Replace (line 152) | func (s Speller) Replace(misspelled, correct string) bool {
    method MainWordList (line 164) | func (s Speller) MainWordList() ([]string, error) {
  function NewSpeller (line 47) | func NewSpeller(options map[string]string) (Speller, error) {
  function wordListToSlice (line 120) | func wordListToSlice(list *C.AspellWordList) []string {
  type Dict (line 173) | type Dict struct
  function Dicts (line 182) | func Dicts() []Dict {

FILE: vendor/github.com/vaughan0/go-ini/ini.go
  type ErrSyntax (line 19) | type ErrSyntax struct
    method Error (line 24) | func (e ErrSyntax) Error() string {
  type File (line 29) | type File
    method Section (line 35) | func (f File) Section(name string) Section {
    method Get (line 45) | func (f File) Get(section, key string) (value string, ok bool) {
    method Load (line 53) | func (f File) Load(in io.Reader) (err error) {
    method LoadFile (line 62) | func (f File) LoadFile(file string) (err error) {
  type Section (line 32) | type Section
  function parseFile (line 71) | func parseFile(in *bufio.Reader, file File) (err error) {
  function Load (line 112) | func Load(in io.Reader) (File, error) {
  function LoadFile (line 119) | func LoadFile(filename string) (File, error) {

FILE: vendor/golang.org/x/crypto/ssh/terminal/terminal.go
  type EscapeCodes (line 16) | type EscapeCodes struct
  type Terminal (line 39) | type Terminal struct
    method queue (line 218) | func (t *Terminal) queue(data []rune) {
    method moveCursorToPos (line 232) | func (t *Terminal) moveCursorToPos(pos int) {
    method move (line 266) | func (t *Terminal) move(up, down, left, right int) {
    method clearLineToRight (line 297) | func (t *Terminal) clearLineToRight() {
    method setLine (line 304) | func (t *Terminal) setLine(newLine []rune, newPos int) {
    method advanceCursor (line 317) | func (t *Terminal) advanceCursor(places int) {
    method eraseNPreviousChars (line 340) | func (t *Terminal) eraseNPreviousChars(n int) {
    method countToLeftWord (line 365) | func (t *Terminal) countToLeftWord() int {
    method countToRightWord (line 390) | func (t *Terminal) countToRightWord() int {
    method handleKey (line 430) | func (t *Terminal) handleKey(key rune) (line string, ok bool) {
    method addKeyToLine (line 567) | func (t *Terminal) addKeyToLine(key rune) {
    method writeLine (line 583) | func (t *Terminal) writeLine(line []rune) {
    method Write (line 596) | func (t *Terminal) Write(buf []byte) (n int, err error) {
    method ReadPassword (line 643) | func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
    method ReadLine (line 660) | func (t *Terminal) ReadLine() (line string, err error) {
    method readLine (line 667) | func (t *Terminal) readLine() (line string, err error) {
    method SetPrompt (line 748) | func (t *Terminal) SetPrompt(prompt string) {
    method clearAndRepaintLinePlusNPrevious (line 755) | func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) {
    method SetSize (line 776) | func (t *Terminal) SetSize(width, height int) error {
    method SetBracketedPasteMode (line 846) | func (t *Terminal) SetBracketedPasteMode(on bool) {
  function NewTerminal (line 101) | func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
  constant keyCtrlD (line 114) | keyCtrlD     = 4
  constant keyCtrlU (line 115) | keyCtrlU     = 21
  constant keyEnter (line 116) | keyEnter     = '\r'
  constant keyEscape (line 117) | keyEscape    = 27
  constant keyBackspace (line 118) | keyBackspace = 127
  constant keyUnknown (line 119) | keyUnknown   = 0xd800 /* UTF-16 surrogate area */ + iota
  constant keyUp (line 120) | keyUp
  constant keyDown (line 121) | keyDown
  constant keyLeft (line 122) | keyLeft
  constant keyRight (line 123) | keyRight
  constant keyAltLeft (line 124) | keyAltLeft
  constant keyAltRight (line 125) | keyAltRight
  constant keyHome (line 126) | keyHome
  constant keyEnd (line 127) | keyEnd
  constant keyDeleteWord (line 128) | keyDeleteWord
  constant keyDeleteLine (line 129) | keyDeleteLine
  constant keyClearScreen (line 130) | keyClearScreen
  constant keyPasteStart (line 131) | keyPasteStart
  constant keyPasteEnd (line 132) | keyPasteEnd
  function bytesToKey (line 140) | func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
  function isPrintable (line 225) | func isPrintable(key rune) bool {
  constant maxLineLength (line 302) | maxLineLength = 4096
  function visualLength (line 408) | func visualLength(runes []rune) int {
  type pasteIndicatorError (line 829) | type pasteIndicatorError struct
    method Error (line 831) | func (pasteIndicatorError) Error() string {
  type stRingBuffer (line 855) | type stRingBuffer struct
    method Add (line 865) | func (s *stRingBuffer) Add(a string) {
    method NthPreviousEntry (line 883) | func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {

FILE: vendor/golang.org/x/crypto/ssh/terminal/util.go
  type State (line 26) | type State struct
  function IsTerminal (line 31) | func IsTerminal(fd int) bool {
  function MakeRaw (line 40) | func MakeRaw(fd int) (*State, error) {
  function GetState (line 58) | func GetState(fd int) (*State, error) {
  function Restore (line 69) | func Restore(fd int, state *State) error {
  function GetSize (line 75) | func GetSize(fd int) (width, height int, err error) {
  function ReadPassword (line 87) | func ReadPassword(fd int) ([]byte, error) {

FILE: vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
  constant ioctlReadTermios (line 11) | ioctlReadTermios = syscall.TIOCGETA
  constant ioctlWriteTermios (line 12) | ioctlWriteTermios = syscall.TIOCSETA

FILE: vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
  constant ioctlReadTermios (line 10) | ioctlReadTermios = 0x5401
  constant ioctlWriteTermios (line 11) | ioctlWriteTermios = 0x5402

FILE: vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
  constant enableLineInput (line 26) | enableLineInput       = 2
  constant enableEchoInput (line 27) | enableEchoInput       = 4
  constant enableProcessedInput (line 28) | enableProcessedInput  = 1
  constant enableWindowInput (line 29) | enableWindowInput     = 8
  constant enableMouseInput (line 30) | enableMouseInput      = 16
  constant enableInsertMode (line 31) | enableInsertMode      = 32
  constant enableQuickEditMode (line 32) | enableQuickEditMode   = 64
  constant enableExtendedFlags (line 33) | enableExtendedFlags   = 128
  constant enableAutoPosition (line 34) | enableAutoPosition    = 256
  constant enableProcessedOutput (line 35) | enableProcessedOutput = 1
  constant enableWrapAtEolOutput (line 36) | enableWrapAtEolOutput = 2
  type short (line 48) | type short
  type word (line 49) | type word
  type coord (line 51) | type coord struct
  type smallRect (line 55) | type smallRect struct
  type consoleScreenBufferInfo (line 61) | type consoleScreenBufferInfo struct
  type State (line 70) | type State struct
  function IsTerminal (line 75) | func IsTerminal(fd int) bool {
  function MakeRaw (line 84) | func MakeRaw(fd int) (*State, error) {
  function GetState (line 100) | func GetState(fd int) (*State, error) {
  function Restore (line 111) | func Restore(fd int, state *State) error {
  function GetSize (line 117) | func GetSize(fd int) (width, height int, err error) {
  function ReadPassword (line 129) | func ReadPassword(fd int) ([]byte, error) {

FILE: vendor/golang.org/x/net/context/context.go
  type Context (line 50) | type Context interface
  type emptyCtx (line 150) | type emptyCtx
    method Deadline (line 152) | func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
    method Done (line 156) | func (*emptyCtx) Done() <-chan struct{} {
    method Err (line 160) | func (*emptyCtx) Err() error {
    method Value (line 164) | func (*emptyCtx) Value(key interface{}) interface{} {
    method String (line 168) | func (e *emptyCtx) String() string {
  function Background (line 187) | func Background() Context {
  function TODO (line 196) | func TODO() Context {
  type CancelFunc (line 203) | type CancelFunc
  function WithCancel (line 211) | func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
  function newCancelCtx (line 218) | func newCancelCtx(parent Context) cancelCtx {
  function propagateCancel (line 226) | func propagateCancel(parent Context, child canceler) {
  function parentCancelCtx (line 256) | func parentCancelCtx(parent Context) (*cancelCtx, bool) {
  function removeChild (line 272) | func removeChild(parent Context, child canceler) {
  type canceler (line 286) | type canceler interface
  type cancelCtx (line 293) | type cancelCtx struct
    method Done (line 303) | func (c *cancelCtx) Done() <-chan struct{} {
    method Err (line 307) | func (c *cancelCtx) Err() error {
    method String (line 313) | func (c *cancelCtx) String() string {
    method cancel (line 319) | func (c *cancelCtx) cancel(removeFromParent bool, err error) {
  function WithDeadline (line 351) | func WithDeadline(parent Context, deadline time.Time) (Context, CancelFu...
  type timerCtx (line 379) | type timerCtx struct
    method Deadline (line 386) | func (c *timerCtx) Deadline() (deadline time.Time, ok bool) {
    method String (line 390) | func (c *timerCtx) String() string {
    method cancel (line 394) | func (c *timerCtx) cancel(removeFromParent bool, err error) {
  function WithTimeout (line 418) | func WithTimeout(parent Context, timeout time.Duration) (Context, Cancel...
  function WithValue (line 427) | func WithValue(parent Context, key interface{}, val interface{}) Context {
  type valueCtx (line 433) | type valueCtx struct
    method String (line 438) | func (c *valueCtx) String() string {
    method Value (line 442) | func (c *valueCtx) Value(key interface{}) interface{} {

FILE: vendor/golang.org/x/oauth2/client_appengine.go
  function init (line 19) | func init() {
  function contextClientAppEngine (line 23) | func contextClientAppEngine(ctx context.Context) (*http.Client, error) {

FILE: vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go
  function tokenFromInternal (line 28) | func tokenFromInternal(t *internal.Token) *oauth2.Token {
  function retrieveToken (line 44) | func retrieveToken(ctx context.Context, c *Config, v url.Values) (*oauth...
  type Config (line 54) | type Config struct
    method Token (line 72) | func (c *Config) Token(ctx context.Context) (*oauth2.Token, error) {
    method Client (line 83) | func (c *Config) Client(ctx context.Context) *http.Client {
    method TokenSource (line 92) | func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource {
  type tokenSource (line 100) | type tokenSource struct
    method Token (line 107) | func (c *tokenSource) Token() (*oauth2.Token, error) {

FILE: vendor/golang.org/x/oauth2/google/appengine.go
  function AppEngineTokenSource (line 26) | func AppEngineTokenSource(ctx context.Context, scope ...string) oauth2.T...
  type tokenLock (line 45) | type tokenLock struct
  type appEngineTokenSource (line 50) | type appEngineTokenSource struct
    method Token (line 56) | func (ts *appEngineTokenSource) Token() (*oauth2.Token, error) {

FILE: vendor/golang.org/x/oauth2/google/appengine_hook.go
  function init (line 11) | func init() {

FILE: vendor/golang.org/x/oauth2/google/default.go
  function DefaultClient (line 33) | func DefaultClient(ctx context.Context, scope ...string) (*http.Client, ...
  function DefaultTokenSource (line 59) | func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.To...
  function wellKnownFile (line 101) | func wellKnownFile() string {
  function tokenSourceFromFile (line 109) | func tokenSourceFromFile(ctx context.Context, filename string, scopes []...

FILE: vendor/golang.org/x/oauth2/google/google.go
  constant JWTTokenURL (line 36) | JWTTokenURL = "https://accounts.google.com/o/oauth2/token"
  function ConfigFromJSON (line 43) | func ConfigFromJSON(jsonKey []byte, scope ...string) (*oauth2.Config, er...
  function JWTConfigFromJSON (line 86) | func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, er...
  function ComputeTokenSource (line 108) | func ComputeTokenSource(account string) oauth2.TokenSource {
  type computeSource (line 112) | type computeSource struct
    method Token (line 116) | func (cs computeSource) Token() (*oauth2.Token, error) {

FILE: vendor/golang.org/x/oauth2/google/sdk.go
  type sdkCredentials (line 24) | type sdkCredentials struct
  type SDKConfig (line 42) | type SDKConfig struct
    method Client (line 127) | func (c *SDKConfig) Client(ctx context.Context) *http.Client {
    method TokenSource (line 140) | func (c *SDKConfig) TokenSource(ctx context.Context) oauth2.TokenSource {
    method Scopes (line 145) | func (c *SDKConfig) Scopes() []string {
  function NewSDKConfig (line 53) | func NewSDKConfig(account string) (*SDKConfig, error) {
  function guessUnixHomeDir (line 162) | func guessUnixHomeDir() string {

FILE: vendor/golang.org/x/oauth2/internal/oauth2.go
  function ParseKey (line 24) | func ParseKey(key []byte) (*rsa.PrivateKey, error) {
  function ParseINI (line 43) | func ParseINI(ini io.Reader) (map[string]map[string]string, error) {
  function CondVal (line 71) | func CondVal(v string) []string {

FILE: vendor/golang.org/x/oauth2/internal/token.go
  type Token (line 30) | type Token struct
  type tokenJSON (line 58) | type tokenJSON struct
    method expiry (line 66) | func (e *tokenJSON) expiry() (t time.Time) {
  type expirationTime (line 76) | type expirationTime
    method UnmarshalJSON (line 78) | func (e *expirationTime) UnmarshalJSON(b []byte) error {
  function providerAuthHeaderWorks (line 122) | func providerAuthHeaderWorks(tokenURL string) bool {
  function RetrieveToken (line 137) | func RetrieveToken(ctx context.Context, ClientID, ClientSecret, TokenURL...

FILE: vendor/golang.org/x/oauth2/internal/transport.go
  type ContextKey (line 21) | type ContextKey struct
  type ContextClientFunc (line 27) | type ContextClientFunc
  function RegisterContextClientFunc (line 31) | func RegisterContextClientFunc(fn ContextClientFunc) {
  function ContextClient (line 35) | func ContextClient(ctx context.Context) (*http.Client, error) {
  function ContextTransport (line 51) | func ContextTransport(ctx context.Context) http.RoundTripper {
  type ErrorTransport (line 63) | type ErrorTransport struct
    method RoundTrip (line 65) | func (t ErrorTransport) RoundTrip(*http.Request) (*http.Response, erro...

FILE: vendor/golang.org/x/oauth2/jws/jws.go
  type ClaimSet (line 26) | type ClaimSet struct
    method encode (line 49) | func (c *ClaimSet) encode() (string, error) {
  type Header (line 90) | type Header struct
    method encode (line 98) | func (h *Header) encode() (string, error) {
  function Decode (line 107) | func Decode(payload string) (*ClaimSet, error) {
  function Encode (line 124) | func Encode(header *Header, c *ClaimSet, signature *rsa.PrivateKey) (str...
  function base64Encode (line 146) | func base64Encode(b []byte) string {
  function base64Decode (line 151) | func base64Decode(s string) ([]byte, error) {

FILE: vendor/golang.org/x/oauth2/jwt/jwt.go
  type Config (line 34) | type Config struct
    method TokenSource (line 61) | func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource {
    method Client (line 70) | func (c *Config) Client(ctx context.Context) *http.Client {
  type jwtSource (line 76) | type jwtSource struct
    method Token (line 81) | func (js jwtSource) Token() (*oauth2.Token, error) {

FILE: vendor/golang.org/x/oauth2/oauth2.go
  type Config (line 28) | type Config struct
    method AuthCodeURL (line 110) | func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) str...
    method PasswordCredentialsToken (line 143) | func (c *Config) PasswordCredentialsToken(ctx context.Context, usernam...
    method Exchange (line 162) | func (c *Config) Exchange(ctx context.Context, code string) (*Token, e...
    method Client (line 175) | func (c *Config) Client(ctx context.Context, t *Token) *http.Client {
    method TokenSource (line 183) | func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource {
  type TokenSource (line 50) | type TokenSource interface
  type Endpoint (line 59) | type Endpoint struct
  type AuthCodeOption (line 86) | type AuthCodeOption interface
  type setParam (line 90) | type setParam struct
    method setValue (line 92) | func (p setParam) setValue(m url.Values) { m.Set(p.k, p.v) }
  function SetAuthURLParam (line 96) | func SetAuthURLParam(key, value string) AuthCodeOption {
  type tokenRefresher (line 199) | type tokenRefresher struct
    method Token (line 209) | func (tf *tokenRefresher) Token() (*Token, error) {
  type reuseTokenSource (line 232) | type reuseTokenSource struct
    method Token (line 242) | func (s *reuseTokenSource) Token() (*Token, error) {
  function StaticTokenSource (line 259) | func StaticTokenSource(t *Token) TokenSource {
  type staticTokenSource (line 264) | type staticTokenSource struct
    method Token (line 268) | func (s staticTokenSource) Token() (*Token, error) {
  function NewClient (line 282) | func NewClient(ctx context.Context, src TokenSource) *http.Client {
  function ReuseTokenSource (line 310) | func ReuseTokenSource(t *Token, src TokenSource) TokenSource {

FILE: vendor/golang.org/x/oauth2/token.go
  constant expiryDelta (line 20) | expiryDelta = 10 * time.Second
  type Token (line 29) | type Token struct
    method Type (line 56) | func (t *Token) Type() string {
    method SetAuthHeader (line 77) | func (t *Token) SetAuthHeader(r *http.Request) {
    method WithExtra (line 84) | func (t *Token) WithExtra(extra interface{}) *Token {
    method Extra (line 94) | func (t *Token) Extra(key string) interface{} {
    method expired (line 107) | func (t *Token) expired() bool {
    method Valid (line 115) | func (t *Token) Valid() bool {
  function tokenFromInternal (line 121) | func tokenFromInternal(t *internal.Token) *Token {
  function retrieveToken (line 137) | func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token...

FILE: vendor/golang.org/x/oauth2/transport.go
  type Transport (line 20) | type Transport struct
    method RoundTrip (line 36) | func (t *Transport) RoundTrip(req *http.Request) (*http.Response, erro...
    method CancelRequest (line 61) | func (t *Transport) CancelRequest(req *http.Request) {
    method base (line 74) | func (t *Transport) base() http.RoundTripper {
    method setModReq (line 81) | func (t *Transport) setModReq(orig, mod *http.Request) {
  function cloneRequest (line 96) | func cloneRequest(r *http.Request) *http.Request {
  type onEOFReader (line 108) | type onEOFReader struct
    method Read (line 113) | func (r *onEOFReader) Read(p []byte) (n int, err error) {
    method Close (line 121) | func (r *onEOFReader) Close() error {
    method runFunc (line 127) | func (r *onEOFReader) runFunc() {

FILE: vendor/google.golang.org/api/bigquery/v2/bigquery-gen.go
  constant apiId (line 39) | apiId = "bigquery:v2"
  constant apiName (line 40) | apiName = "bigquery"
  constant apiVersion (line 41) | apiVersion = "v2"
  constant basePath (line 42) | basePath = "https://www.googleapis.com/bigquery/v2/"
  constant BigqueryScope (line 47) | BigqueryScope = "https://www.googleapis.com/auth/bigquery"
  constant BigqueryInsertdataScope (line 50) | BigqueryInsertdataScope = "https://www.googleapis.com/auth/bigquery.inse...
  constant CloudPlatformScope (line 53) | CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"
  constant DevstorageFullControlScope (line 56) | DevstorageFullControlScope = "https://www.googleapis.com/auth/devstorage...
  constant DevstorageReadOnlyScope (line 59) | DevstorageReadOnlyScope = "https://www.googleapis.com/auth/devstorage.re...
  constant DevstorageReadWriteScope (line 62) | DevstorageReadWriteScope = "https://www.googleapis.com/auth/devstorage.r...
  function New (line 65) | func New(client *http.Client) (*Service, error) {
  type Service (line 78) | type Service struct
    method userAgent (line 94) | func (s *Service) userAgent() string {
  function NewDatasetsService (line 101) | func NewDatasetsService(s *Service) *DatasetsService {
  type DatasetsService (line 106) | type DatasetsService struct
    method Delete (line 1269) | func (r *DatasetsService) Delete(projectId string, datasetId string) *...
    method Get (line 1365) | func (r *DatasetsService) Get(projectId string, datasetId string) *Dat...
    method Insert (line 1452) | func (r *DatasetsService) Insert(projectId string, dataset *Dataset) *...
    method List (line 1540) | func (r *DatasetsService) List(projectId string) *DatasetsListCall {
    method Patch (line 1668) | func (r *DatasetsService) Patch(projectId string, datasetId string, da...
    method Update (line 1768) | func (r *DatasetsService) Update(projectId string, datasetId string, d...
  function NewJobsService (line 110) | func NewJobsService(s *Service) *JobsService {
  type JobsService (line 115) | type JobsService struct
    method Get (line 1867) | func (r *JobsService) Get(projectId string, jobId string) *JobsGetCall {
    method GetQueryResults (line 1954) | func (r *JobsService) GetQueryResults(projectId string, jobId string) ...
    method Insert (line 2112) | func (r *JobsService) Insert(projectId string, job *Job) *JobsInsertCa...
    method List (line 2293) | func (r *JobsService) List(projectId string) *JobsListCall {
    method Query (line 2476) | func (r *JobsService) Query(projectId string, queryrequest *QueryReque...
  function NewProjectsService (line 119) | func NewProjectsService(s *Service) *ProjectsService {
  type ProjectsService (line 124) | type ProjectsService struct
    method List (line 2563) | func (r *ProjectsService) List() *ProjectsListCall {
  function NewTabledataService (line 128) | func NewTabledataService(s *Service) *TabledataService {
  type TabledataService (line 133) | type TabledataService struct
    method InsertAll (line 2663) | func (r *TabledataService) InsertAll(projectId string, datasetId strin...
    method List (line 2772) | func (r *TabledataService) List(projectId string, datasetId string, ta...
  function NewTablesService (line 137) | func NewTablesService(s *Service) *TablesService {
  type TablesService (line 142) | type TablesService struct
    method Delete (line 2917) | func (r *TablesService) Delete(projectId string, datasetId string, tab...
    method Get (line 3009) | func (r *TablesService) Get(projectId string, datasetId string, tableI...
    method Insert (line 3106) | func (r *TablesService) Insert(projectId string, datasetId string, tab...
    method List (line 3204) | func (r *TablesService) List(projectId string, datasetId string) *Tabl...
    method Patch (line 3327) | func (r *TablesService) Patch(projectId string, datasetId string, tabl...
    method Update (line 3437) | func (r *TablesService) Update(projectId string, datasetId string, tab...
  type CsvOptions (line 146) | type CsvOptions struct
  type Dataset (line 189) | type Dataset struct
  type DatasetAccess (line 253) | type DatasetAccess struct
  type DatasetList (line 287) | type DatasetList struct
  type DatasetListDatasets (line 307) | type DatasetListDatasets struct
  type DatasetReference (line 323) | type DatasetReference struct
  type ErrorProto (line 333) | type ErrorProto struct
  type ExternalDataConfiguration (line 348) | type ExternalDataConfiguration struct
  type GetQueryResultsResponse (line 387) | type GetQueryResultsResponse struct
  type Job (line 433) | type Job struct
  type JobConfiguration (line 466) | type JobConfiguration struct
  type JobConfigurationExtract (line 489) | type JobConfigurationExtract struct
  type JobConfigurationLink (line 522) | type JobConfigurationLink struct
  type JobConfigurationLoad (line 551) | type JobConfigurationLoad struct
  type JobConfigurationQuery (line 670) | type JobConfigurationQuery struct
  type JobConfigurationTableCopy (line 736) | type JobConfigurationTableCopy struct
  type JobList (line 768) | type JobList struct
  type JobListJobs (line 785) | type JobListJobs struct
  type JobReference (line 819) | type JobReference struct
  type JobStatistics (line 829) | type JobStatistics struct
  type JobStatistics2 (line 858) | type JobStatistics2 struct
  type JobStatistics3 (line 868) | type JobStatistics3 struct
  type JobStatistics4 (line 887) | type JobStatistics4 struct
  type JobStatus (line 895) | type JobStatus struct
  type JsonValue (line 909) | type JsonValue interface
  type ProjectList (line 911) | type ProjectList struct
  type ProjectListProjects (line 928) | type ProjectListProjects struct
  type ProjectReference (line 945) | type ProjectReference struct
  type QueryRequest (line 951) | type QueryRequest struct
  type QueryResponse (line 998) | type QueryResponse struct
  type Table (line 1041) | type Table struct
  type TableCell (line 1100) | type TableCell struct
  type TableDataInsertAllRequest (line 1104) | type TableDataInsertAllRequest struct
  type TableDataInsertAllRequestRows (line 1122) | type TableDataInsertAllRequestRows struct
  type TableDataInsertAllResponse (line 1134) | type TableDataInsertAllResponse struct
  type TableDataInsertAllResponseInsertErrors (line 1142) | type TableDataInsertAllResponseInsertErrors struct
  type TableDataList (line 1151) | type TableDataList struct
  type TableFieldSchema (line 1170) | type TableFieldSchema struct
  type TableList (line 1194) | type TableList struct
  type TableListTables (line 1211) | type TableListTables struct
  type TableReference (line 1228) | type TableReference struct
  type TableRow (line 1241) | type TableRow struct
  type TableSchema (line 1245) | type TableSchema struct
  type ViewDefinition (line 1250) | type ViewDefinition struct
  type DatasetsDeleteCall (line 1258) | type DatasetsDeleteCall struct
    method DeleteContents (line 1279) | func (c *DatasetsDeleteCall) DeleteContents(deleteContents bool) *Data...
    method Fields (line 1287) | func (c *DatasetsDeleteCall) Fields(s ...googleapi.Field) *DatasetsDel...
    method Do (line 1292) | func (c *DatasetsDeleteCall) Do() error {
  type DatasetsGetCall (line 1357) | type DatasetsGetCall struct
    method Fields (line 1375) | func (c *DatasetsGetCall) Fields(s ...googleapi.Field) *DatasetsGetCall {
    method Do (line 1380) | func (c *DatasetsGetCall) Do() (*Dataset, error) {
  type DatasetsInsertCall (line 1444) | type DatasetsInsertCall struct
    method Fields (line 1462) | func (c *DatasetsInsertCall) Fields(s ...googleapi.Field) *DatasetsIns...
    method Do (line 1467) | func (c *DatasetsInsertCall) Do() (*Dataset, error) {
  type DatasetsListCall (line 1532) | type DatasetsListCall struct
    method All (line 1548) | func (c *DatasetsListCall) All(all bool) *DatasetsListCall {
    method MaxResults (line 1555) | func (c *DatasetsListCall) MaxResults(maxResults int64) *DatasetsListC...
    method PageToken (line 1562) | func (c *DatasetsListCall) PageToken(pageToken string) *DatasetsListCa...
    method Fields (line 1570) | func (c *DatasetsListCall) Fields(s ...googleapi.Field) *DatasetsListC...
    method Do (line 1575) | func (c *DatasetsListCall) Do() (*DatasetList, error) {
  type DatasetsPatchCall (line 1656) | type DatasetsPatchCall struct
    method Fields (line 1679) | func (c *DatasetsPatchCall) Fields(s ...googleapi.Field) *DatasetsPatc...
    method Do (line 1684) | func (c *DatasetsPatchCall) Do() (*Dataset, error) {
  type DatasetsUpdateCall (line 1757) | type DatasetsUpdateCall struct
    method Fields (line 1779) | func (c *DatasetsUpdateCall) Fields(s ...googleapi.Field) *DatasetsUpd...
    method Do (line 1784) | func (c *DatasetsUpdateCall) Do() (*Dataset, error) {
  type JobsGetCall (line 1857) | type JobsGetCall struct
    method Fields (line 1877) | func (c *JobsGetCall) Fields(s ...googleapi.Field) *JobsGetCall {
    method Do (line 1882) | func (c *JobsGetCall) Do() (*Job, error) {
  type JobsGetQueryResultsCall (line 1946) | type JobsGetQueryResultsCall struct
    method MaxResults (line 1963) | func (c *JobsGetQueryResultsCall) MaxResults(maxResults int64) *JobsGe...
    method PageToken (line 1970) | func (c *JobsGetQueryResultsCall) PageToken(pageToken string) *JobsGet...
    method StartIndex (line 1977) | func (c *JobsGetQueryResultsCall) StartIndex(startIndex uint64) *JobsG...
    method TimeoutMs (line 1986) | func (c *JobsGetQueryResultsCall) TimeoutMs(timeoutMs int64) *JobsGetQ...
    method Fields (line 1994) | func (c *JobsGetQueryResultsCall) Fields(s ...googleapi.Field) *JobsGe...
    method Do (line 1999) | func (c *JobsGetQueryResultsCall) Do() (*GetQueryResultsResponse, erro...
  type JobsInsertCall (line 2098) | type JobsInsertCall struct
    method Media (line 2121) | func (c *JobsInsertCall) Media(r io.Reader) *JobsInsertCall {
    method ResumableMedia (line 2131) | func (c *JobsInsertCall) ResumableMedia(ctx context.Context, r io.Read...
    method ProgressUpdater (line 2142) | func (c *JobsInsertCall) ProgressUpdater(pu googleapi.ProgressUpdater)...
    method Fields (line 2150) | func (c *JobsInsertCall) Fields(s ...googleapi.Field) *JobsInsertCall {
    method Do (line 2155) | func (c *JobsInsertCall) Do() (*Job, error) {
  type JobsListCall (line 2282) | type JobsListCall struct
    method AllUsers (line 2301) | func (c *JobsListCall) AllUsers(allUsers bool) *JobsListCall {
    method MaxResults (line 2308) | func (c *JobsListCall) MaxResults(maxResults int64) *JobsListCall {
    method PageToken (line 2315) | func (c *JobsListCall) PageToken(pageToken string) *JobsListCall {
    method Projection (line 2326) | func (c *JobsListCall) Projection(projection string) *JobsListCall {
    method StateFilter (line 2338) | func (c *JobsListCall) StateFilter(stateFilter string) *JobsListCall {
    method Fields (line 2346) | func (c *JobsListCall) Fields(s ...googleapi.Field) *JobsListCall {
    method Do (line 2351) | func (c *JobsListCall) Do() (*JobList, error) {
  type JobsQueryCall (line 2467) | type JobsQueryCall struct
    method Fields (line 2486) | func (c *JobsQueryCall) Fields(s ...googleapi.Field) *JobsQueryCall {
    method Do (line 2491) | func (c *JobsQueryCall) Do() (*QueryResponse, error) {
  type ProjectsListCall (line 2556) | type ProjectsListCall struct
    method MaxResults (line 2570) | func (c *ProjectsListCall) MaxResults(maxResults int64) *ProjectsListC...
    method PageToken (line 2577) | func (c *ProjectsListCall) PageToken(pageToken string) *ProjectsListCa...
    method Fields (line 2585) | func (c *ProjectsListCall) Fields(s ...googleapi.Field) *ProjectsListC...
    method Do (line 2590) | func (c *ProjectsListCall) Do() (*ProjectList, error) {
  type TabledataInsertAllCall (line 2652) | type TabledataInsertAllCall struct
    method Fields (line 2675) | func (c *TabledataInsertAllCall) Fields(s ...googleapi.Field) *Tableda...
    method Do (line 2680) | func (c *TabledataInsertAllCall) Do() (*TableDataInsertAllResponse, er...
  type TabledataListCall (line 2762) | type TabledataListCall struct
    method MaxResults (line 2782) | func (c *TabledataListCall) MaxResults(maxResults int64) *TabledataLis...
    method PageToken (line 2789) | func (c *TabledataListCall) PageToken(pageToken string) *TabledataList...
    method StartIndex (line 2796) | func (c *TabledataListCall) StartIndex(startIndex uint64) *TabledataLi...
    method Fields (line 2804) | func (c *TabledataListCall) Fields(s ...googleapi.Field) *TabledataLis...
    method Do (line 2809) | func (c *TabledataListCall) Do() (*TableDataList, error) {
  type TablesDeleteCall (line 2907) | type TablesDeleteCall struct
    method Fields (line 2928) | func (c *TablesDeleteCall) Fields(s ...googleapi.Field) *TablesDeleteC...
    method Do (line 2933) | func (c *TablesDeleteCall) Do() error {
  type TablesGetCall (line 2998) | type TablesGetCall struct
    method Fields (line 3020) | func (c *TablesGetCall) Fields(s ...googleapi.Field) *TablesGetCall {
    method Do (line 3025) | func (c *TablesGetCall) Do() (*Table, error) {
  type TablesInsertCall (line 3097) | type TablesInsertCall struct
    method Fields (line 3117) | func (c *TablesInsertCall) Fields(s ...googleapi.Field) *TablesInsertC...
    method Do (line 3122) | func (c *TablesInsertCall) Do() (*Table, error) {
  type TablesListCall (line 3195) | type TablesListCall struct
    method MaxResults (line 3213) | func (c *TablesListCall) MaxResults(maxResults int64) *TablesListCall {
    method PageToken (line 3220) | func (c *TablesListCall) PageToken(pageToken string) *TablesListCall {
    method Fields (line 3228) | func (c *TablesListCall) Fields(s ...googleapi.Field) *TablesListCall {
    method Do (line 3233) | func (c *TablesListCall) Do() (*TableList, error) {
  type TablesPatchCall (line 3314) | type TablesPatchCall struct
    method Fields (line 3339) | func (c *TablesPatchCall) Fields(s ...googleapi.Field) *TablesPatchCall {
    method Do (line 3344) | func (c *TablesPatchCall) Do() (*Table, error) {
  type TablesUpdateCall (line 3425) | type TablesUpdateCall struct
    method Fields (line 3449) | func (c *TablesUpdateCall) Fields(s ...googleapi.Field) *TablesUpdateC...
    method Do (line 3454) | func (c *TablesUpdateCall) Do() (*Table, error) {

FILE: vendor/google.golang.org/api/container/v1beta1/container-gen.go
  constant apiId (line 39) | apiId = "container:v1beta1"
  constant apiName (line 40) | apiName = "container"
  constant apiVersion (line 41) | apiVersion = "v1beta1"
  constant basePath (line 42) | basePath = "https://www.googleapis.com/container/v1beta1/projects/"
  constant CloudPlatformScope (line 47) | CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"
  function New (line 50) | func New(client *http.Client) (*Service, error) {
  type Service (line 59) | type Service struct
    method userAgent (line 67) | func (s *Service) userAgent() string {
  function NewProjectsService (line 74) | func NewProjectsService(s *Service) *ProjectsService {
  type ProjectsService (line 82) | type ProjectsService struct
  function NewProjectsClustersService (line 92) | func NewProjectsClustersService(s *Service) *ProjectsClustersService {
  type ProjectsClustersService (line 97) | type ProjectsClustersService struct
    method List (line 363) | func (r *ProjectsClustersService) List(projectId string) *ProjectsClus...
  function NewProjectsOperationsService (line 101) | func NewProjectsOperationsService(s *Service) *ProjectsOperationsService {
  type ProjectsOperationsService (line 106) | type ProjectsOperationsService struct
    method List (line 439) | func (r *ProjectsOperationsService) List(projectId string) *ProjectsOp...
  function NewProjectsZonesService (line 110) | func NewProjectsZonesService(s *Service) *ProjectsZonesService {
  type ProjectsZonesService (line 117) | type ProjectsZonesService struct
  function NewProjectsZonesClustersService (line 125) | func NewProjectsZonesClustersService(s *Service) *ProjectsZonesClustersS...
  type ProjectsZonesClustersService (line 130) | type ProjectsZonesClustersService struct
    method Create (line 529) | func (r *ProjectsZonesClustersService) Create(projectId string, zoneId...
    method Delete (line 630) | func (r *ProjectsZonesClustersService) Delete(projectId string, zoneId...
    method Get (line 726) | func (r *ProjectsZonesClustersService) Get(projectId string, zoneId st...
    method List (line 821) | func (r *ProjectsZonesClustersService) List(projectId string, zoneId s...
  function NewProjectsZonesOperationsService (line 134) | func NewProjectsZonesOperationsService(s *Service) *ProjectsZonesOperati...
  type ProjectsZonesOperationsService (line 139) | type ProjectsZonesOperationsService struct
    method Get (line 908) | func (r *ProjectsZonesOperationsService) Get(projectId string, zoneId ...
    method List (line 1003) | func (r *ProjectsZonesOperationsService) List(projectId string, zoneId...
  type Cluster (line 143) | type Cluster struct
  type CreateClusterRequest (line 235) | type CreateClusterRequest struct
  type ListAggregatedClustersResponse (line 240) | type ListAggregatedClustersResponse struct
  type ListAggregatedOperationsResponse (line 245) | type ListAggregatedOperationsResponse struct
  type ListClustersResponse (line 250) | type ListClustersResponse struct
  type ListOperationsResponse (line 255) | type ListOperationsResponse struct
  type MasterAuth (line 261) | type MasterAuth struct
  type NodeConfig (line 278) | type NodeConfig struct
  type Operation (line 307) | type Operation struct
  type ServiceAccount (line 345) | type ServiceAccount struct
  type ProjectsClustersListCall (line 356) | type ProjectsClustersListCall struct
    method Fields (line 372) | func (c *ProjectsClustersListCall) Fields(s ...googleapi.Field) *Proje...
    method Do (line 377) | func (c *ProjectsClustersListCall) Do() (*ListAggregatedClustersRespon...
  type ProjectsOperationsListCall (line 432) | type ProjectsOperationsListCall struct
    method Fields (line 448) | func (c *ProjectsOperationsListCall) Fields(s ...googleapi.Field) *Pro...
    method Do (line 453) | func (c *ProjectsOperationsListCall) Do() (*ListAggregatedOperationsRe...
  type ProjectsZonesClustersCreateCall (line 508) | type ProjectsZonesClustersCreateCall struct
    method Fields (line 540) | func (c *ProjectsZonesClustersCreateCall) Fields(s ...googleapi.Field)...
    method Do (line 545) | func (c *ProjectsZonesClustersCreateCall) Do() (*Operation, error) {
  type ProjectsZonesClustersDeleteCall (line 617) | type ProjectsZonesClustersDeleteCall struct
    method Fields (line 641) | func (c *ProjectsZonesClustersDeleteCall) Fields(s ...googleapi.Field)...
    method Do (line 646) | func (c *ProjectsZonesClustersDeleteCall) Do() (*Operation, error) {
  type ProjectsZonesClustersGetCall (line 717) | type ProjectsZonesClustersGetCall struct
    method Fields (line 737) | func (c *ProjectsZonesClustersGetCall) Fields(s ...googleapi.Field) *P...
    method Do (line 742) | func (c *ProjectsZonesClustersGetCall) Do() (*Cluster, error) {
  type ProjectsZonesClustersListCall (line 813) | type ProjectsZonesClustersListCall struct
    method Fields (line 831) | func (c *ProjectsZonesClustersListCall) Fields(s ...googleapi.Field) *...
    method Do (line 836) | func (c *ProjectsZonesClustersListCall) Do() (*ListClustersResponse, e...
  type ProjectsZonesOperationsGetCall (line 899) | type ProjectsZonesOperationsGetCall struct
    method Fields (line 919) | func (c *ProjectsZonesOperationsGetCall) Fields(s ...googleapi.Field) ...
    method Do (line 924) | func (c *ProjectsZonesOperationsGetCall) Do() (*Operation, error) {
  type ProjectsZonesOperationsListCall (line 995) | type ProjectsZonesOperationsListCall struct
    method Fields (line 1013) | func (c *ProjectsZonesOperationsListCall) Fields(s ...googleapi.Field)...
    method Do (line 1018) | func (c *ProjectsZonesOperationsListCall) Do() (*ListOperationsRespons...

FILE: vendor/google.golang.org/api/googleapi/googleapi.go
  type ContentTyper (line 34) | type ContentTyper interface
  type SizeReaderAt (line 40) | type SizeReaderAt interface
  constant Version (line 46) | Version = "0.5"
  constant statusResumeIncomplete (line 49) | statusResumeIncomplete = 308
  constant UserAgent (line 52) | UserAgent = "google-api-go-client/" + Version
  constant uploadPause (line 55) | uploadPause = 1 * time.Second
  type Error (line 59) | type Error struct
    method Error (line 80) | func (e *Error) Error() string {
  type ErrorItem (line 73) | type ErrorItem struct
  type errorReply (line 103) | type errorReply struct
  function CheckResponse (line 109) | func CheckResponse(res *http.Response) error {
  type MarshalStyle (line 131) | type MarshalStyle
    method JSONReader (line 136) | func (wrap MarshalStyle) JSONReader(v interface{}) (io.Reader, error) {
  function getMediaType (line 151) | func getMediaType(media io.Reader) (io.Reader, string) {
  function DetectMediaType (line 178) | func DetectMediaType(media io.ReaderAt) string {
  type Lengther (line 193) | type Lengther interface
  type endingWithErrorReader (line 199) | type endingWithErrorReader struct
    method Read (line 204) | func (er endingWithErrorReader) Read(p []byte) (n int, err error) {
  function typeHeader (line 212) | func typeHeader(contentType string) textproto.MIMEHeader {
  type countingWriter (line 220) | type countingWriter struct
    method Write (line 224) | func (w countingWriter) Write(p []byte) (int, error) {
  function ConditionallyIncludeMedia (line 240) | func ConditionallyIncludeMedia(media io.Reader, bodyp *io.Reader, ctypep...
  type ProgressUpdater (line 292) | type ProgressUpdater
  type ResumableUpload (line 296) | type ResumableUpload struct
    method Progress (line 324) | func (rx *ResumableUpload) Progress() int64 {
    method transferStatus (line 330) | func (rx *ResumableUpload) transferStatus() (int64, *http.Response, er...
    method transferChunks (line 356) | func (rx *ResumableUpload) transferChunks(ctx context.Context) (*http....
    method Upload (line 402) | func (rx *ResumableUpload) Upload(ctx context.Context) (*http.Response...
  type chunk (line 350) | type chunk struct
  function ResolveRelative (line 421) | func ResolveRelative(basestr, relstr string) string {
  function init (line 436) | func init() {
  function SetOpaque (line 450) | func SetOpaque(u *url.URL) {
  function Expand (line 461) | func Expand(u *url.URL, expansions map[string]string) {
  function CloseBody (line 472) | func CloseBody(res *http.Response) {
  function VariantType (line 495) | func VariantType(t map[string]interface{}) string {
  function ConvertVariant (line 503) | func ConvertVariant(v map[string]interface{}, dst interface{}) bool {
  type Field (line 535) | type Field
  function CombineFields (line 538) | func CombineFields(s []Field) string {

FILE: vendor/google.golang.org/api/googleapi/internal/uritemplates/uritemplates.go
  function pctEncode (line 37) | func pctEncode(src []byte) []byte {
  function escape (line 48) | func escape(s string, allowReserved bool) (escaped string) {
  type UriTemplate (line 58) | type UriTemplate struct
    method Expand (line 188) | func (self *UriTemplate) Expand(value interface{}) (string, error) {
  function Parse (line 64) | func Parse(rawtemplate string) (template *UriTemplate, err error) {
  type templatePart (line 96) | type templatePart struct
    method expand (line 207) | func (self *templatePart) expand(buf *bytes.Buffer, values map[string]...
    method expandName (line 253) | func (self *templatePart) expandName(buf *bytes.Buffer, name string, e...
    method expandString (line 264) | func (self *templatePart) expandString(buf *bytes.Buffer, t templateTe...
    method expandArray (line 272) | func (self *templatePart) expandArray(buf *bytes.Buffer, t templateTer...
    method expandMap (line 301) | func (self *templatePart) expandMap(buf *bytes.Buffer, t templateTerm,...
  type templateTerm (line 106) | type templateTerm struct
  function parseExpression (line 112) | func parseExpression(expression string) (result templatePart, err error) {
  function parseTerm (line 162) | func parseTerm(term string) (result templateTerm, err error) {
  function struct2map (line 336) | func struct2map(v interface{}) (map[string]interface{}, bool) {

FILE: vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go
  function Expand (line 3) | func Expand(path string, expansions map[string]string) (string, error) {

FILE: vendor/google.golang.org/api/googleapi/transport/apikey.go
  type APIKey (line 16) | type APIKey struct
    method RoundTrip (line 25) | func (t *APIKey) RoundTrip(req *http.Request) (*http.Response, error) {

FILE: vendor/google.golang.org/api/googleapi/types.go
  type Int64s (line 13) | type Int64s
    method UnmarshalJSON (line 15) | func (q *Int64s) UnmarshalJSON(raw []byte) error {
    method MarshalJSON (line 122) | func (s Int64s) MarshalJSON() ([]byte, error) {
  type Int32s (line 32) | type Int32s
    method UnmarshalJSON (line 34) | func (q *Int32s) UnmarshalJSON(raw []byte) error {
    method MarshalJSON (line 128) | func (s Int32s) MarshalJSON() ([]byte, error) {
  type Uint64s (line 51) | type Uint64s
    method UnmarshalJSON (line 53) | func (q *Uint64s) UnmarshalJSON(raw []byte) error {
    method MarshalJSON (line 134) | func (s Uint64s) MarshalJSON() ([]byte, error) {
  type Uint32s (line 70) | type Uint32s
    method UnmarshalJSON (line 72) | func (q *Uint32s) UnmarshalJSON(raw []byte) error {
    method MarshalJSON (line 140) | func (s Uint32s) MarshalJSON() ([]byte, error) {
  type Float64s (line 89) | type Float64s
    method UnmarshalJSON (line 91) | func (q *Float64s) UnmarshalJSON(raw []byte) error {
    method MarshalJSON (line 146) | func (s Float64s) MarshalJSON() ([]byte, error) {
  function quotedList (line 107) | func quotedList(n int, fn func(dst []byte, i int) []byte) ([]byte, error) {

FILE: vendor/google.golang.org/api/pubsub/v1beta2/pubsub-gen.go
  constant apiId (line 37) | apiId = "pubsub:v1beta2"
  constant apiName (line 38) | apiName = "pubsub"
  constant apiVersion (line 39) | apiVersion = "v1beta2"
  constant basePath (line 40) | basePath = "https://pubsub.googleapis.com/v1beta2/"
  constant CloudPlatformScope (line 45) | CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"
  constant PubsubScope (line 48) | PubsubScope = "https://www.googleapis.com/auth/pubsub"
  function New (line 51) | func New(client *http.Client) (*Service, error) {
  type Service (line 60) | type Service struct
    method userAgent (line 68) | func (s *Service) userAgent() string {
  function NewProjectsService (line 75) | func NewProjectsService(s *Service) *ProjectsService {
  type ProjectsService (line 82) | type ProjectsService struct
  function NewProjectsSubscriptionsService (line 90) | func NewProjectsSubscriptionsService(s *Service) *ProjectsSubscriptionsS...
  type ProjectsSubscriptionsService (line 95) | type ProjectsSubscriptionsService struct
    method Acknowledge (line 222) | func (r *ProjectsSubscriptionsService) Acknowledge(subscription string...
    method Create (line 314) | func (r *ProjectsSubscriptionsService) Create(name string, subscriptio...
    method Delete (line 405) | func (r *ProjectsSubscriptionsService) Delete(subscription string) *Pr...
    method Get (line 481) | func (r *ProjectsSubscriptionsService) Get(subscription string) *Proje...
    method List (line 557) | func (r *ProjectsSubscriptionsService) List(project string) *ProjectsS...
    method ModifyAckDeadline (line 664) | func (r *ProjectsSubscriptionsService) ModifyAckDeadline(subscription ...
    method ModifyPushConfig (line 756) | func (r *ProjectsSubscriptionsService) ModifyPushConfig(subscription s...
    method Pull (line 846) | func (r *ProjectsSubscriptionsService) Pull(subscription string, pullr...
  function NewProjectsTopicsService (line 99) | func NewProjectsTopicsService(s *Service) *ProjectsTopicsService {
  type ProjectsTopicsService (line 105) | type ProjectsTopicsService struct
    method Create (line 933) | func (r *ProjectsTopicsService) Create(name string, topic *Topic) *Pro...
    method Delete (line 1023) | func (r *ProjectsTopicsService) Delete(topic string) *ProjectsTopicsDe...
    method Get (line 1099) | func (r *ProjectsTopicsService) Get(topic string) *ProjectsTopicsGetCa...
    method List (line 1175) | func (r *ProjectsTopicsService) List(project string) *ProjectsTopicsLi...
    method Publish (line 1280) | func (r *ProjectsTopicsService) Publish(topic string, publishrequest *...
  function NewProjectsTopicsSubscriptionsService (line 111) | func NewProjectsTopicsSubscriptionsService(s *Service) *ProjectsTopicsSu...
  type ProjectsTopicsSubscriptionsService (line 116) | type ProjectsTopicsSubscriptionsService struct
    method List (line 1366) | func (r *ProjectsTopicsSubscriptionsService) List(topic string) *Proje...
  type AcknowledgeRequest (line 120) | type AcknowledgeRequest struct
  type Empty (line 124) | type Empty struct
  type ListSubscriptionsResponse (line 127) | type ListSubscriptionsResponse struct
  type ListTopicSubscriptionsResponse (line 133) | type ListTopicSubscriptionsResponse struct
  type ListTopicsResponse (line 139) | type ListTopicsResponse struct
  type ModifyAckDeadlineRequest (line 145) | type ModifyAckDeadlineRequest struct
  type ModifyPushConfigRequest (line 151) | type ModifyPushConfigRequest struct
  type PublishRequest (line 155) | type PublishRequest struct
  type PublishResponse (line 159) | type PublishResponse struct
  type PubsubMessage (line 163) | type PubsubMessage struct
  type PullRequest (line 171) | type PullRequest struct
  type PullResponse (line 177) | type PullResponse struct
  type PushConfig (line 181) | type PushConfig struct
  type ReceivedMessage (line 187) | type ReceivedMessage struct
  type Subscription (line 193) | type Subscription struct
  type Topic (line 203) | type Topic struct
  type ProjectsSubscriptionsAcknowledgeCall (line 209) | type ProjectsSubscriptionsAcknowledgeCall struct
    method Fields (line 232) | func (c *ProjectsSubscriptionsAcknowledgeCall) Fields(s ...googleapi.F...
    method Do (line 237) | func (c *ProjectsSubscriptionsAcknowledgeCall) Do() (*Empty, error) {
  type ProjectsSubscriptionsCreateCall (line 301) | type ProjectsSubscriptionsCreateCall struct
    method Fields (line 324) | func (c *ProjectsSubscriptionsCreateCall) Fields(s ...googleapi.Field)...
    method Do (line 329) | func (c *ProjectsSubscriptionsCreateCall) Do() (*Subscription, error) {
  type ProjectsSubscriptionsDeleteCall (line 393) | type ProjectsSubscriptionsDeleteCall struct
    method Fields (line 414) | func (c *ProjectsSubscriptionsDeleteCall) Fields(s ...googleapi.Field)...
    method Do (line 419) | func (c *ProjectsSubscriptionsDeleteCall) Do() (*Empty, error) {
  type ProjectsSubscriptionsGetCall (line 474) | type ProjectsSubscriptionsGetCall struct
    method Fields (line 490) | func (c *ProjectsSubscriptionsGetCall) Fields(s ...googleapi.Field) *P...
    method Do (line 495) | func (c *ProjectsSubscriptionsGetCall) Do() (*Subscription, error) {
  type ProjectsSubscriptionsListCall (line 550) | type ProjectsSubscriptionsListCall struct
    method PageSize (line 564) | func (c *ProjectsSubscriptionsListCall) PageSize(pageSize int64) *Proj...
    method PageToken (line 570) | func (c *ProjectsSubscriptionsListCall) PageToken(pageToken string) *P...
    method Fields (line 578) | func (c *ProjectsSubscriptionsListCall) Fields(s ...googleapi.Field) *...
    method Do (line 583) | func (c *ProjectsSubscriptionsListCall) Do() (*ListSubscriptionsRespon...
  type ProjectsSubscriptionsModifyAckDeadlineCall (line 653) | type ProjectsSubscriptionsModifyAckDeadlineCall struct
    method Fields (line 674) | func (c *ProjectsSubscriptionsModifyAckDeadlineCall) Fields(s ...googl...
    method Do (line 679) | func (c *ProjectsSubscriptionsModifyAckDeadlineCall) Do() (*Empty, err...
  type ProjectsSubscriptionsModifyPushConfigCall (line 743) | type ProjectsSubscriptionsModifyPushConfigCall struct
    method Fields (line 766) | func (c *ProjectsSubscriptionsModifyPushConfigCall) Fields(s ...google...
    method Do (line 771) | func (c *ProjectsSubscriptionsModifyPushConfigCall) Do() (*Empty, erro...
  type ProjectsSubscriptionsPullCall (line 835) | type ProjectsSubscriptionsPullCall struct
    method Fields (line 856) | func (c *ProjectsSubscriptionsPullCall) Fields(s ...googleapi.Field) *...
    method Do (line 861) | func (c *ProjectsSubscriptionsPullCall) Do() (*PullResponse, error) {
  type ProjectsTopicsCreateCall (line 925) | type ProjectsTopicsCreateCall struct
    method Fields (line 943) | func (c *ProjectsTopicsCreateCall) Fields(s ...googleapi.Field) *Proje...
    method Do (line 948) | func (c *ProjectsTopicsCreateCall) Do() (*Topic, error) {
  type ProjectsTopicsDeleteCall (line 1012) | type ProjectsTopicsDeleteCall struct
    method Fields (line 1032) | func (c *ProjectsTopicsDeleteCall) Fields(s ...googleapi.Field) *Proje...
    method Do (line 1037) | func (c *ProjectsTopicsDeleteCall) Do() (*Empty, error) {
  type ProjectsTopicsGetCall (line 1092) | type ProjectsTopicsGetCall struct
    method Fields (line 1108) | func (c *ProjectsTopicsGetCall) Fields(s ...googleapi.Field) *Projects...
    method Do (line 1113) | func (c *ProjectsTopicsGetCall) Do() (*Topic, error) {
  type ProjectsTopicsListCall (line 1168) | type ProjectsTopicsListCall struct
    method PageSize (line 1182) | func (c *ProjectsTopicsListCall) PageSize(pageSize int64) *ProjectsTop...
    method PageToken (line 1188) | func (c *ProjectsTopicsListCall) PageToken(pageToken string) *Projects...
    method Fields (line 1196) | func (c *ProjectsTopicsListCall) Fields(s ...googleapi.Field) *Project...
    method Do (line 1201) | func (c *ProjectsTopicsListCall) Do() (*ListTopicsResponse, error) {
  type ProjectsTopicsPublishCall (line 1271) | type ProjectsTopicsPublishCall struct
    method Fields (line 1290) | func (c *ProjectsTopicsPublishCall) Fields(s ...googleapi.Field) *Proj...
    method Do (line 1295) | func (c *ProjectsTopicsPublishCall) Do() (*PublishResponse, error) {
  type ProjectsTopicsSubscriptionsListCall (line 1359) | type ProjectsTopicsSubscriptionsListCall struct
    method PageSize (line 1373) | func (c *ProjectsTopicsSubscriptionsListCall) PageSize(pageSize int64)...
    method PageToken (line 1379) | func (c *ProjectsTopicsSubscriptionsListCall) PageToken(pageToken stri...
    method Fields (line 1387) | func (c *ProjectsTopicsSubscriptionsListCall) Fields(s ...googleapi.Fi...
    method Do (line 1392) | func (c *ProjectsTopicsSubscriptionsListCall) Do() (*ListTopicSubscrip...

FILE: vendor/google.golang.org/api/storage/v1/storage-gen.go
  constant apiId (line 39) | apiId = "storage:v1"
  constant apiName (line 40) | apiName = "storage"
  constant apiVersion (line 41) | apiVersion = "v1"
  constant basePath (line 42) | basePath = "https://www.googleapis.com/storage/v1/"
  constant CloudPlatformScope (line 47) | CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"
  constant DevstorageFullControlScope (line 50) | DevstorageFullControlScope = "https://www.googleapis.com/auth/devstorage...
  constant DevstorageReadOnlyScope (line 53) | DevstorageReadOnlyScope = "https://www.googleapis.com/auth/devstorage.re...
  constant DevstorageReadWriteScope (line 56) | DevstorageReadWriteScope = "https://www.googleapis.com/auth/devstorage.r...
  function New (line 59) | func New(client *http.Client) (*Service, error) {
  type Service (line 73) | type Service struct
    method userAgent (line 91) | func (s *Service) userAgent() string {
  function NewBucketAccessControlsService (line 98) | func NewBucketAccessControlsService(s *Service) *BucketAccessControlsSer...
  type BucketAccessControlsService (line 103) | type BucketAccessControlsService struct
    method Delete (line 694) | func (r *BucketAccessControlsService) Delete(bucket string, entity str...
    method Get (line 774) | func (r *BucketAccessControlsService) Get(bucket string, entity string...
    method Insert (line 860) | func (r *BucketAccessControlsService) Insert(bucket string, bucketacce...
    method List (line 946) | func (r *BucketAccessControlsService) List(bucket string) *BucketAcces...
    method Patch (line 1025) | func (r *BucketAccessControlsService) Patch(bucket string, entity stri...
    method Update (line 1122) | func (r *BucketAccessControlsService) Update(bucket string, entity str...
  function NewBucketsService (line 107) | func NewBucketsService(s *Service) *BucketsService {
  type BucketsService (line 112) | type BucketsService struct
    method Delete (line 1217) | func (r *BucketsService) Delete(bucket string) *BucketsDeleteCall {
    method Get (line 1322) | func (r *BucketsService) Get(bucket string) *BucketsGetCall {
    method Insert (line 1465) | func (r *BucketsService) Insert(projectid string, bucket *Bucket) *Buc...
    method List (line 1666) | func (r *BucketsService) List(projectid string) *BucketsListCall {
    method Patch (line 1820) | func (r *BucketsService) Patch(bucket string, bucket2 *Bucket) *Bucket...
    method Update (line 2057) | func (r *BucketsService) Update(bucket string, bucket2 *Bucket) *Bucke...
  function NewChannelsService (line 116) | func NewChannelsService(s *Service) *ChannelsService {
  type ChannelsService (line 121) | type ChannelsService struct
    method Stop (line 2293) | func (r *ChannelsService) Stop(channel *Channel) *ChannelsStopCall {
  function NewDefaultObjectAccessControlsService (line 125) | func NewDefaultObjectAccessControlsService(s *Service) *DefaultObjectAcc...
  type DefaultObjectAccessControlsService (line 130) | type DefaultObjectAccessControlsService struct
    method Delete (line 2364) | func (r *DefaultObjectAccessControlsService) Delete(bucket string, ent...
    method Get (line 2444) | func (r *DefaultObjectAccessControlsService) Get(bucket string, entity...
    method Insert (line 2531) | func (r *DefaultObjectAccessControlsService) Insert(bucket string, obj...
    method List (line 2617) | func (r *DefaultObjectAccessControlsService) List(bucket string) *Defa...
    method Patch (line 2731) | func (r *DefaultObjectAccessControlsService) Patch(bucket string, enti...
    method Update (line 2828) | func (r *DefaultObjectAccessControlsService) Update(bucket string, ent...
  function NewObjectAccessControlsService (line 134) | func NewObjectAccessControlsService(s *Service) *ObjectAccessControlsSer...
  type ObjectAccessControlsService (line 139) | type ObjectAccessControlsService struct
    method Delete (line 2926) | func (r *ObjectAccessControlsService) Delete(bucket string, object str...
    method Get (line 3033) | func (r *ObjectAccessControlsService) Get(bucket string, object string...
    method Insert (line 3146) | func (r *ObjectAccessControlsService) Insert(bucket string, object str...
    method List (line 3259) | func (r *ObjectAccessControlsService) List(bucket string, object strin...
    method Patch (line 3365) | func (r *ObjectAccessControlsService) Patch(bucket string, object stri...
    method Update (line 3489) | func (r *ObjectAccessControlsService) Update(bucket string, object str...
  function NewObjectsService (line 143) | func NewObjectsService(s *Service) *ObjectsService {
  type ObjectsService (line 148) | type ObjectsService struct
    method Compose (line 3613) | func (r *ObjectsService) Compose(destinationBucket string, destination...
    method Copy (line 3795) | func (r *ObjectsService) Copy(sourceBucket string, sourceObject string...
    method Delete (line 4146) | func (r *ObjectsService) Delete(bucket string, object string) *Objects...
    method Get (line 4313) | func (r *ObjectsService) Get(bucket string, object string) *ObjectsGet...
    method Insert (line 4521) | func (r *ObjectsService) Insert(bucket string, object *Object) *Object...
    method List (line 4873) | func (r *ObjectsService) List(bucket string) *ObjectsListCall {
    method Patch (line 5068) | func (r *ObjectsService) Patch(bucket string, object string, object2 *...
    method Rewrite (line 5327) | func (r *ObjectsService) Rewrite(sourceBucket string, sourceObject str...
    method Update (line 5718) | func (r *ObjectsService) Update(bucket string, object string, object2 ...
    method WatchAll (line 5974) | func (r *ObjectsService) WatchAll(bucket string, channel *Channel) *Ob...
  type Bucket (line 152) | type Bucket struct
  type BucketCors (line 221) | type BucketCors struct
  type BucketLifecycle (line 242) | type BucketLifecycle struct
  type BucketLifecycleRule (line 248) | type BucketLifecycleRule struct
  type BucketLifecycleRuleAction (line 256) | type BucketLifecycleRuleAction struct
  type BucketLifecycleRuleCondition (line 261) | type BucketLifecycleRuleCondition struct
  type BucketLogging (line 282) | type BucketLogging struct
  type BucketOwner (line 291) | type BucketOwner struct
  type BucketVersioning (line 299) | type BucketVersioning struct
  type BucketWebsite (line 305) | type BucketWebsite struct
  type BucketAccessControl (line 315) | type BucketAccessControl struct
  type BucketAccessControlProjectTeam (line 366) | type BucketAccessControlProjectTeam struct
  type BucketAccessControls (line 374) | type BucketAccessControls struct
  type Buckets (line 383) | type Buckets struct
  type Channel (line 397) | type Channel struct
  type ComposeRequest (line 436) | type ComposeRequest struct
  type ComposeRequestSourceObjects (line 448) | type ComposeRequestSourceObjects struct
  type ComposeRequestSourceObjectsObjectPreconditions (line 461) | type ComposeRequestSourceObjectsObjectPreconditions struct
  type Object (line 469) | type Object struct
  type ObjectOwner (line 556) | type ObjectOwner struct
  type ObjectAccessControl (line 564) | type ObjectAccessControl struct
  type ObjectAccessControlProjectTeam (line 620) | type ObjectAccessControlProjectTeam struct
  type ObjectAccessControls (line 628) | type ObjectAccessControls struct
  type Objects (line 637) | type Objects struct
  type RewriteResponse (line 655) | type RewriteResponse struct
  type BucketAccessControlsDeleteCall (line 685) | type BucketAccessControlsDeleteCall struct
    method Fields (line 704) | func (c *BucketAccessControlsDeleteCall) Fields(s ...googleapi.Field) ...
    method Do (line 709) | func (c *BucketAccessControlsDeleteCall) Do() error {
  type BucketAccessControlsGetCall (line 765) | type BucketAccessControlsGetCall struct
    method Fields (line 784) | func (c *BucketAccessControlsGetCall) Fields(s ...googleapi.Field) *Bu...
    method Do (line 789) | func (c *BucketAccessControlsGetCall) Do() (*BucketAccessControl, erro...
  type BucketAccessControlsInsertCall (line 852) | type BucketAccessControlsInsertCall struct
    method Fields (line 870) | func (c *BucketAccessControlsInsertCall) Fields(s ...googleapi.Field) ...
    method Do (line 875) | func (c *BucketAccessControlsInsertCall) Do() (*BucketAccessControl, e...
  type BucketAccessControlsListCall (line 939) | type BucketAccessControlsListCall struct
    method Fields (line 955) | func (c *BucketAccessControlsListCall) Fields(s ...googleapi.Field) *B...
    method Do (line 960) | func (c *BucketAccessControlsListCall) Do() (*BucketAccessControls, er...
  type BucketAccessControlsPatchCall (line 1015) | type BucketAccessControlsPatchCall struct
    method Fields (line 1036) | func (c *BucketAccessControlsPatchCall) Fields(s ...googleapi.Field) *...
    method Do (line 1041) | func (c *BucketAccessControlsPatchCall) Do() (*BucketAccessControl, er...
  type BucketAccessControlsUpdateCall (line 1113) | type BucketAccessControlsUpdateCall struct
    method Fields (line 1133) | func (c *BucketAccessControlsUpdateCall) Fields(s ...googleapi.Field) ...
    method Do (line 1138) | func (c *BucketAccessControlsUpdateCall) Do() (*BucketAccessControl, e...
  type BucketsDeleteCall (line 1210) | type BucketsDeleteCall struct
    method IfMetagenerationMatch (line 1226) | func (c *BucketsDeleteCall) IfMetagenerationMatch(ifMetagenerationMatc...
    method IfMetagenerationNotMatch (line 1234) | func (c *BucketsDeleteCall) IfMetagenerationNotMatch(ifMetagenerationN...
    method Fields (line 1242) | func (c *BucketsDeleteCall) Fields(s ...googleapi.Field) *BucketsDelet...
    method Do (line 1247) | func (c *BucketsDeleteCall) Do() error {
  type BucketsGetCall (line 1315) | type BucketsGetCall struct
    method IfMetagenerationMatch (line 1332) | func (c *BucketsGetCall) IfMetagenerationMatch(ifMetagenerationMatch i...
    method IfMetagenerationNotMatch (line 1341) | func (c *BucketsGetCall) IfMetagenerationNotMatch(ifMetagenerationNotM...
    method Projection (line 1352) | func (c *BucketsGetCall) Projection(projection string) *BucketsGetCall {
    method Fields (line 1360) | func (c *BucketsGetCall) Fields(s ...googleapi.Field) *BucketsGetCall {
    method Do (line 1365) | func (c *BucketsGetCall) Do() (*Bucket, error) {
  type BucketsInsertCall (line 1457) | type BucketsInsertCall struct
    method PredefinedAcl (line 1485) | func (c *BucketsInsertCall) PredefinedAcl(predefinedAcl string) *Bucke...
    method PredefinedDefaultObjectAcl (line 1506) | func (c *BucketsInsertCall) PredefinedDefaultObjectAcl(predefinedDefau...
    method Projection (line 1519) | func (c *BucketsInsertCall) Projection(projection string) *BucketsInse...
    method Fields (line 1527) | func (c *BucketsInsertCall) Fields(s ...googleapi.Field) *BucketsInser...
    method Do (line 1532) | func (c *BucketsInsertCall) Do() (*Bucket, error) {
  type BucketsListCall (line 1659) | type BucketsListCall struct
    method MaxResults (line 1674) | func (c *BucketsListCall) MaxResults(maxResults int64) *BucketsListCall {
    method PageToken (line 1682) | func (c *BucketsListCall) PageToken(pageToken string) *BucketsListCall {
    method Prefix (line 1689) | func (c *BucketsListCall) Prefix(prefix string) *BucketsListCall {
    method Projection (line 1700) | func (c *BucketsListCall) Projection(projection string) *BucketsListCa...
    method Fields (line 1708) | func (c *BucketsListCall) Fields(s ...googleapi.Field) *BucketsListCall {
    method Do (line 1713) | func (c *BucketsListCall) Do() (*Buckets, error) {
  type BucketsPatchCall (line 1812) | type BucketsPatchCall struct
    method IfMetagenerationMatch (line 1831) | func (c *BucketsPatchCall) IfMetagenerationMatch(ifMetagenerationMatch...
    method IfMetagenerationNotMatch (line 1840) | func (c *BucketsPatchCall) IfMetagenerationNotMatch(ifMetagenerationNo...
    method PredefinedAcl (line 1858) | func (c *BucketsPatchCall) PredefinedAcl(predefinedAcl string) *Bucket...
    method PredefinedDefaultObjectAcl (line 1879) | func (c *BucketsPatchCall) PredefinedDefaultObjectAcl(predefinedDefaul...
    method Projection (line 1890) | func (c *BucketsPatchCall) Projection(projection string) *BucketsPatch...
    method Fields (line 1898) | func (c *BucketsPatchCall) Fields(s ...googleapi.Field) *BucketsPatchC...
    method Do (line 1903) | func (c *BucketsPatchCall) Do() (*Bucket, error) {
  type BucketsUpdateCall (line 2049) | type BucketsUpdateCall struct
    method IfMetagenerationMatch (line 2068) | func (c *BucketsUpdateCall) IfMetagenerationMatch(ifMetagenerationMatc...
    method IfMetagenerationNotMatch (line 2077) | func (c *BucketsUpdateCall) IfMetagenerationNotMatch(ifMetagenerationN...
    method PredefinedAcl (line 2095) | func (c *BucketsUpdateCall) PredefinedAcl(predefinedAcl string) *Bucke...
    method PredefinedDefaultObjectAcl (line 2116) | func (c *BucketsUpdateCall) PredefinedDefaultObjectAcl(predefinedDefau...
    method Projection (line 2127) | func (c *BucketsUpdateCall) Projection(projection string) *BucketsUpda...
    method Fields (line 2135) | func (c *BucketsUpdateCall) Fields(s ...googleapi.Field) *BucketsUpdat...
    method Do (line 2140) | func (c *BucketsUpdateCall) Do() (*Bucket, error) {
  type ChannelsStopCall (line 2286) | type ChannelsStopCall struct
    method Fields (line 2302) | func (c *ChannelsStopCall) Fields(s ...googleapi.Field) *ChannelsStopC...
    method Do (line 2307) | func (c *ChannelsStopCall) Do() error {
  type DefaultObjectAccessControlsDeleteCall (line 2355) | type DefaultObjectAccessControlsDeleteCall struct
    method Fields (line 2374) | func (c *DefaultObjectAccessControlsDeleteCall) Fields(s ...googleapi....
    method Do (line 2379) | func (c *DefaultObjectAccessControlsDeleteCall) Do() error {
  type DefaultObjectAccessControlsGetCall (line 2435) | type DefaultObjectAccessControlsGetCall struct
    method Fields (line 2454) | func (c *DefaultObjectAccessControlsGetCall) Fields(s ...googleapi.Fie...
    method Do (line 2459) | func (c *DefaultObjectAccessControlsGetCall) Do() (*ObjectAccessContro...
  type DefaultObjectAccessControlsInsertCall (line 2522) | type DefaultObjectAccessControlsInsertCall struct
    method Fields (line 2541) | func (c *DefaultObjectAccessControlsInsertCall) Fields(s ...googleapi....
    method Do (line 2546) | func (c *DefaultObjectAccessControlsInsertCall) Do() (*ObjectAccessCon...
  type DefaultObjectAccessControlsListCall (line 2610) | type DefaultObjectAccessControlsListCall struct
    method IfMetagenerationMatch (line 2626) | func (c *DefaultObjectAccessControlsListCall) IfMetagenerationMatch(if...
    method IfMetagenerationNotMatch (line 2635) | func (c *DefaultObjectAccessControlsListCall) IfMetagenerationNotMatch...
    method Fields (line 2643) | func (c *DefaultObjectAccessControlsListCall) Fields(s ...googleapi.Fi...
    method Do (line 2648) | func (c *DefaultObjectAccessControlsListCall) Do() (*ObjectAccessContr...
  type DefaultObjectAccessControlsPatchCall (line 2721) | type DefaultObjectAccessControlsPatchCall struct
    method Fields (line 2742) | func (c *DefaultObjectAccessControlsPatchCall) Fields(s ...googleapi.F...
    method Do (line 2747) | func (c *DefaultObjectAccessControlsPatchCall) Do() (*ObjectAccessCont...
  type DefaultObjectAccessControlsUpdateCall (line 2819) | type DefaultObjectAccessControlsUpdateCall struct
    method Fields (line 2839) | func (c *DefaultObjectAccessControlsUpdateCall) Fields(s ...googleapi....
    method Do (line 2844) | func (c *DefaultObjectAccessControlsUpdateCall) Do() (*ObjectAccessCon...
  type ObjectAccessControlsDeleteCall (line 2916) | type ObjectAccessControlsDeleteCall struct
    method Generation (line 2937) | func (c *ObjectAccessControlsDeleteCall) Generation(generation int64) ...
    method Fields (line 2945) | func (c *ObjectAccessControlsDeleteCall) Fields(s ...googleapi.Field) ...
    method Do (line 2950) | func (c *ObjectAccessControlsDeleteCall) Do() error {
  type ObjectAccessControlsGetCall (line 3023) | type ObjectAccessControlsGetCall struct
    method Generation (line 3044) | func (c *ObjectAccessControlsGetCall) Generation(generation int64) *Ob...
    method Fields (line 3052) | func (c *ObjectAccessControlsGetCall) Fields(s ...googleapi.Field) *Ob...
    method Do (line 3057) | func (c *ObjectAccessControlsGetCall) Do() (*ObjectAccessControl, erro...
  type ObjectAccessControlsInsertCall (line 3137) | type ObjectAccessControlsInsertCall struct
    method Generation (line 3157) | func (c *ObjectAccessControlsInsertCall) Generation(generation int64) ...
    method Fields (line 3165) | func (c *ObjectAccessControlsInsertCall) Fields(s ...googleapi.Field) ...
    method Do (line 3170) | func (c *ObjectAccessControlsInsertCall) Do() (*ObjectAccessControl, e...
  type ObjectAccessControlsListCall (line 3251) | type ObjectAccessControlsListCall struct
    method Generation (line 3269) | func (c *ObjectAccessControlsListCall) Generation(generation int64) *O...
    method Fields (line 3277) | func (c *ObjectAccessControlsListCall) Fields(s ...googleapi.Field) *O...
    method Do (line 3282) | func (c *ObjectAccessControlsListCall) Do() (*ObjectAccessControls, er...
  type ObjectAccessControlsPatchCall (line 3354) | type ObjectAccessControlsPatchCall struct
    method Generation (line 3377) | func (c *ObjectAccessControlsPatchCall) Generation(generation int64) *...
    method Fields (line 3385) | func (c *ObjectAccessControlsPatchCall) Fields(s ...googleapi.Field) *...
    method Do (line 3390) | func (c *ObjectAccessControlsPatchCall) Do() (*ObjectAccessControl, er...
  type ObjectAccessControlsUpdateCall (line 3479) | type ObjectAccessControlsUpdateCall struct
    method Generation (line 3501) | func (c *ObjectAccessControlsUpdateCall) Generation(generation int64) ...
    method Fields (line 3509) | func (c *ObjectAccessControlsUpdateCall) Fields(s ...googleapi.Field) ...
    method Do (line 3514) | func (c *ObjectAccessControlsUpdateCall) Do() (*ObjectAccessControl, e...
  type ObjectsComposeCall (line 3603) | type ObjectsComposeCall struct
    method DestinationPredefinedAcl (line 3637) | func (c *ObjectsComposeCall) DestinationPredefinedAcl(destinationPrede...
    method IfGenerationMatch (line 3645) | func (c *ObjectsComposeCall) IfGenerationMatch(ifGenerationMatch int64...
    method IfMetagenerationMatch (line 3653) | func (c *ObjectsComposeCall) IfMetagenerationMatch(ifMetagenerationMat...
    method Fields (line 3661) | func (c *ObjectsComposeCall) Fields(s ...googleapi.Field) *ObjectsComp...
    method Do (line 3666) | func (c *ObjectsComposeCall) Do() (*Object, error) {
  type ObjectsCopyCall (line 3783) | type ObjectsCopyCall struct
    method DestinationPredefinedAcl (line 3821) | func (c *ObjectsCopyCall) DestinationPredefinedAcl(destinationPredefin...
    method IfGenerationMatch (line 3829) | func (c *ObjectsCopyCall) IfGenerationMatch(ifGenerationMatch int64) *...
    method IfGenerationNotMatch (line 3838) | func (c *ObjectsCopyCall) IfGenerationNotMatch(ifGenerationNotMatch in...
    method IfMetagenerationMatch (line 3847) | func (c *ObjectsCopyCall) IfMetagenerationMatch(ifMetagenerationMatch ...
    method IfMetagenerationNotMatch (line 3856) | func (c *ObjectsCopyCall) IfMetagenerationNotMatch(ifMetagenerationNot...
    method IfSourceGenerationMatch (line 3864) | func (c *ObjectsCopyCall) IfSourceGenerationMatch(ifSourceGenerationMa...
    method IfSourceGenerationNotMatch (line 3873) | func (c *ObjectsCopyCall) IfSourceGenerationNotMatch(ifSourceGeneratio...
    method IfSourceMetagenerationMatch (line 3882) | func (c *ObjectsCopyCall) IfSourceMetagenerationMatch(ifSourceMetagene...
    method IfSourceMetagenerationNotMatch (line 3891) | func (c *ObjectsCopyCall) IfSourceMetagenerationNotMatch(ifSourceMetag...
    method Projection (line 3903) | func (c *ObjectsCopyCall) Projection(projection string) *ObjectsCopyCa...
    method SourceGeneration (line 3911) | func (c *ObjectsCopyCall) SourceGeneration(sourceGeneration int64) *Ob...
    method Fields (line 3919) | func (c *ObjectsCopyCall) Fields(s ...googleapi.Field) *ObjectsCopyCall {
    method Do (line 3924) | func (c *ObjectsCopyCall) Do() (*Object, error) {
  type ObjectsDeleteCall (line 4136) | type ObjectsDeleteCall struct
    method Generation (line 4156) | func (c *ObjectsDeleteCall) Generation(generation int64) *ObjectsDelet...
    method IfGenerationMatch (line 4164) | func (c *ObjectsDeleteCall) IfGenerationMatch(ifGenerationMatch int64)...
    method IfGenerationNotMatch (line 4172) | func (c *ObjectsDeleteCall) IfGenerationNotMatch(ifGenerationNotMatch ...
    method IfMetagenerationMatch (line 4180) | func (c *ObjectsDeleteCall) IfMetagenerationMatch(ifMetagenerationMatc...
    method IfMetagenerationNotMatch (line 4189) | func (c *ObjectsDeleteCall) IfMetagenerationNotMatch(ifMetagenerationN...
    method Fields (line 4197) | func (c *ObjectsDeleteCall) Fields(s ...googleapi.Field) *ObjectsDelet...
    method Do (line 4202) | func (c *ObjectsDeleteCall) Do() error {
  type ObjectsGetCall (line 4305) | type ObjectsGetCall struct
    method Generation (line 4323) | func (c *ObjectsGetCall) Generation(generation int64) *ObjectsGetCall {
    method IfGenerationMatch (line 4331) | func (c *ObjectsGetCall) IfGenerationMatch(ifGenerationMatch int64) *O...
    method IfGenerationNotMatch (line 4339) | func (c *ObjectsGetCall) IfGenerationNotMatch(ifGenerationNotMatch int...
    method IfMetagenerationMatch (line 4347) | func (c *ObjectsGetCall) IfMetagenerationMatch(ifMetagenerationMatch i...
    method IfMetagenerationNotMatch (line 4356) | func (c *ObjectsGetCall) IfMetagenerationNotMatch(ifMetage
Condensed preview — 424 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,462K chars).
[
  {
    "path": ".buildpacks",
    "chars": 106,
    "preview": "https://github.com/mcollina/heroku-buildpack-graphicsmagick\nhttps://github.com/kr/heroku-buildpack-go.git\n"
  },
  {
    "path": ".gitignore",
    "chars": 304,
    "preview": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Architecture spe"
  },
  {
    "path": ".travis.yml",
    "chars": 268,
    "preview": "sudo: required\n\nservices:\n  - docker\n\nbefore_install:\n  - docker build -t imgur/mandible .\n\nscript:\n  - docker run -e \"C"
  },
  {
    "path": "Dockerfile",
    "chars": 617,
    "preview": "FROM golang:1.8-stretch\nRUN apt-get update && apt-get install -yqq aspell aspell-en libaspell-dev tesseract-ocr tesserac"
  },
  {
    "path": "Godeps/Godeps.json",
    "chars": 2335,
    "preview": "{\n\t\"ImportPath\": \"github.com/Imgur/mandible\",\n\t\"GoVersion\": \"go1.5\",\n\t\"Packages\": [\n\t\t\"./...\"\n\t],\n\t\"Deps\": [\n\t\t{\n\t\t\t\"Imp"
  },
  {
    "path": "Godeps/Readme",
    "chars": 136,
    "preview": "This directory tree is generated automatically by godep.\n\nPlease do not edit.\n\nSee https://github.com/tools/godep for mo"
  },
  {
    "path": "LICENSE",
    "chars": 1078,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 Imgur, Inc.\n\nPermission is hereby granted, free of charge, to any person obtai"
  },
  {
    "path": "Procfile",
    "chars": 13,
    "preview": "web: ImgurGo\n"
  },
  {
    "path": "README.md",
    "chars": 7184,
    "preview": "# mandible ![TravisStatus](https://travis-ci.org/Imgur/mandible.svg) [![Coverage Status](https://coveralls.io/repos/Imgu"
  },
  {
    "path": "app.json",
    "chars": 612,
    "preview": "{\n  \"name\": \"ImgurGo\",\n  \"description\": \"An easy Heroku image uploading service\",\n  \"repository\": \"https://github.com/go"
  },
  {
    "path": "config/config.go",
    "chars": 622,
    "preview": "package config\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n)\n\ntype Configuration struct {\n\tMaxFileSize     int64\n\tHashLength"
  },
  {
    "path": "config/default.conf.json",
    "chars": 1014,
    "preview": "{\n    \"Port\": 8080,\n    \"MaxFileSize\": 20971520,\n    \"HashLength\": 7,\n    \"UserAgent\": \"ImgurGo (https://github.com/goph"
  },
  {
    "path": "docker/build_gm.sh",
    "chars": 2015,
    "preview": "#!/bin/bash\n\napt-get install -y libjpeg-dev liblcms2-dev libwmf-dev libx11-dev libsm-dev libice-dev libxext-dev x11proto"
  },
  {
    "path": "docker/conf.json",
    "chars": 383,
    "preview": "{\n    \"Port\": 8080,\n    \"MaxFileSize\": 20971520,\n    \"HashLength\": 7,\n    \"UserAgent\": \"Mandible (https://github.com/Img"
  },
  {
    "path": "goclean.sh",
    "chars": 1411,
    "preview": "#!/bin/bash\n# The script does automatic checking on a Go package and its sub-packages, including:\n# 1. gofmt         (ht"
  },
  {
    "path": "imageprocessor/compresslosslessly.go",
    "chars": 987,
    "preview": "package imageprocessor\n\nimport (\n\t\"errors\"\n\n\t\"github.com/Imgur/mandible/imageprocessor/processorcommand\"\n\t\"github.com/Im"
  },
  {
    "path": "imageprocessor/exifstripper.go",
    "chars": 457,
    "preview": "package imageprocessor\n\nimport (\n\t\"github.com/Imgur/mandible/imageprocessor/processorcommand\"\n\t\"github.com/Imgur/mandibl"
  },
  {
    "path": "imageprocessor/imageorienter.go",
    "chars": 459,
    "preview": "package imageprocessor\n\nimport (\n\t\"github.com/Imgur/mandible/imageprocessor/processorcommand\"\n\t\"github.com/Imgur/mandibl"
  },
  {
    "path": "imageprocessor/imageprocessor.go",
    "chars": 3026,
    "preview": "package imageprocessor\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/Imgur/mandible/config\"\n\t\"github.com/Imgur/mandible/uplo"
  },
  {
    "path": "imageprocessor/imagescaler.go",
    "chars": 2059,
    "preview": "package imageprocessor\n\nimport (\n\t\"errors\"\n\n\t\"github.com/Imgur/mandible/imageprocessor/processorcommand\"\n\t\"github.com/Im"
  },
  {
    "path": "imageprocessor/ocr.go",
    "chars": 957,
    "preview": "package imageprocessor\n\nimport (\n\t\"github.com/Imgur/mandible/imageprocessor/processorcommand\"\n\t\"github.com/Imgur/mandibl"
  },
  {
    "path": "imageprocessor/ocr_test.go",
    "chars": 1263,
    "preview": "package imageprocessor\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/Imgur/mandible/uploadedfile"
  },
  {
    "path": "imageprocessor/processorcommand/gm.go",
    "chars": 4713,
    "preview": "package processorcommand\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/Imgur/mandible/imageprocessor/thumbType\"\n)\n\nconst GM_COMMAND = \""
  },
  {
    "path": "imageprocessor/processorcommand/jpegtran.go",
    "chars": 342,
    "preview": "package processorcommand\n\nimport (\n\t\"fmt\"\n)\n\nfunc Jpegtran(filename string) (string, error) {\n\toutfile := fmt.Sprintf(\"%"
  },
  {
    "path": "imageprocessor/processorcommand/ocrcommands.go",
    "chars": 4359,
    "preview": "package processorcommand\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/trustmaster/go"
  },
  {
    "path": "imageprocessor/processorcommand/optipng.go",
    "chars": 310,
    "preview": "package processorcommand\n\nimport (\n\t\"fmt\"\n)\n\nfunc Optipng(filename string) (string, error) {\n\toutfile := fmt.Sprintf(\"%s"
  },
  {
    "path": "imageprocessor/processorcommand/runner.go",
    "chars": 721,
    "preview": "package processorcommand\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"log\"\n\t\"os/exec\"\n\t\"time\"\n)\n\nfunc runProcessorCommand(command stri"
  },
  {
    "path": "imageprocessor/processorcommand/stripmetadata.go",
    "chars": 258,
    "preview": "package processorcommand\n\nfunc StripMetadata(filename string) error {\n\targs := []string{\n\t\t\"-all=\",\n\t\t\"--icc_profile:all"
  },
  {
    "path": "imageprocessor/thumbType/thumbType.go",
    "chars": 738,
    "preview": "package thumbType\n\ntype ThumbType int\n\nconst (\n\tUNKNOWN ThumbType = iota\n\tJPG\n\tPNG\n\tGIF\n\tWEBP\n)\n\nfunc (this ThumbType) T"
  },
  {
    "path": "imagestore/factory.go",
    "chars": 2738,
    "preview": "package imagestore\n\nimport (\n\t\"io/ioutil\"\n\t\"log\"\n\n\t\"github.com/Imgur/mandible/config\"\n\t\"github.com/mitchellh/goamz/aws\"\n"
  },
  {
    "path": "imagestore/gcsstore.go",
    "chars": 1959,
    "preview": "package imagestore\n\nimport (\n\t\"io\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n\n\t\"golang.org/x/net/context\"\n\t\"google.golang.org/cloud/stor"
  },
  {
    "path": "imagestore/hash.go",
    "chars": 1545,
    "preview": "package imagestore\n\nimport (\n\t\"crypto/rand\"\n\t\"log\"\n)\n\n// Provides a continuous stream of random image \"hashes\" of a fixe"
  },
  {
    "path": "imagestore/localstore.go",
    "chars": 1531,
    "preview": "package imagestore\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"path\"\n)\n\n// A LocalImageStore stores images on the local disk.\ntype LocalImag"
  },
  {
    "path": "imagestore/memorystore.go",
    "chars": 1215,
    "preview": "package imagestore\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"strings\"\n\t\"sync\"\n)\n\ntype InMemoryImageStore struct {\n\t"
  },
  {
    "path": "imagestore/namepathmapper.go",
    "chars": 606,
    "preview": "package imagestore\n\nimport (\n\t\"regexp\"\n\t\"strings\"\n)\n\ntype NamePathMapper struct {\n\tregex   *regexp.Regexp\n\treplace strin"
  },
  {
    "path": "imagestore/s3store.go",
    "chars": 1598,
    "preview": "package imagestore\n\nimport (\n\t\"io\"\n\t\"os\"\n\n\t\"github.com/mitchellh/goamz/s3\"\n)\n\ntype S3ImageStore struct {\n\tbucketName    "
  },
  {
    "path": "imagestore/store.go",
    "chars": 2190,
    "preview": "package imagestore\n\nimport (\n\t\"fmt\"\n\t\"io\"\n)\n\ntype ImageStore interface {\n\tSave(src string, obj *StoreObject) (*StoreObje"
  },
  {
    "path": "imagestore/storeobject.go",
    "chars": 450,
    "preview": "package imagestore\n\ntype StorableObject interface {\n\tGetPath() string\n}\n\ntype StoreObject struct {\n\tId       string // U"
  },
  {
    "path": "main.go",
    "chars": 1224,
    "preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\n\tmandibleConf \"github.com/Imgur/mandible/config\"\n\tprocessors \"gi"
  },
  {
    "path": "server/authenticator.go",
    "chars": 2414,
    "preview": "package server\n\nimport (\n\t\"crypto/hmac\"\n\t\"crypto/sha256\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"hash\"\n\t\"net/htt"
  },
  {
    "path": "server/authenticator_test.go",
    "chars": 3878,
    "preview": "package server\n\nimport (\n\t\"crypto/hmac\"\n\t\"crypto/sha256\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"testing\"\n\t\"ti"
  },
  {
    "path": "server/server.go",
    "chars": 17625,
    "preview": "package server\n\nimport (\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"net/http\"\n\t\"os"
  },
  {
    "path": "server/server_test.go",
    "chars": 25715,
    "preview": "package server\n\nimport (\n\t\"bytes\"\n\t\"crypto/hmac\"\n\t\"crypto/sha256\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"net"
  },
  {
    "path": "server/stats.go",
    "chars": 2079,
    "preview": "package server\n\nimport (\n\t\"fmt\"\n\t\"net\"\n\t\"time\"\n\n\t\"github.com/PagerDuty/godspeed\"\n)\n\ntype RuntimeStats interface {\n\tLogSt"
  },
  {
    "path": "uploadedfile/thumbfile.go",
    "chars": 6606,
    "preview": "package uploadedfile\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"math\"\n\t\"os\"\n\t\"regexp\"\n\t\"strconv\"\n\n\t\"github.com/Imgur/mandible/imagepro"
  },
  {
    "path": "uploadedfile/uploadedfile.go",
    "chars": 2956,
    "preview": "package uploadedfile\n\nimport (\n\t\"errors\"\n\t\"image\"\n\t\"image/gif\"\n\t\"image/jpeg\"\n\t\"image/png\"\n\t\"net/http\"\n\t\"os\"\n)\n\ntype Uplo"
  },
  {
    "path": "vendor/github.com/PagerDuty/godspeed/.gitignore",
    "chars": 280,
    "preview": "# Misc\n*.swp\n\n# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Ar"
  },
  {
    "path": "vendor/github.com/PagerDuty/godspeed/.travis.yml",
    "chars": 105,
    "preview": "language: go\ngo:\n  - 1.5.3\nbranches:\n  only:\n    - master\nscript: go test -v ./... -check.vv\nsudo: false\n"
  },
  {
    "path": "vendor/github.com/PagerDuty/godspeed/LICENSE",
    "chars": 1483,
    "preview": "Copyright (c) 2014-2015, PagerDuty Inc.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or"
  },
  {
    "path": "vendor/github.com/PagerDuty/godspeed/README.md",
    "chars": 1969,
    "preview": "# Godspeed\n[![TravisCI Build Status](https://img.shields.io/travis/PagerDuty/godspeed/master.svg?style=flat)](https://tr"
  },
  {
    "path": "vendor/github.com/PagerDuty/godspeed/async.go",
    "chars": 5051,
    "preview": "// Copyright 2014-2015 PagerDuty, Inc, et al. All rights reserved.\n// Use of this source code is governed by the BSD 3-C"
  },
  {
    "path": "vendor/github.com/PagerDuty/godspeed/events.go",
    "chars": 2138,
    "preview": "// Copyright 2014-2015 PagerDuty, Inc, et al. All rights reserved.\n// Use of this source code is governed by the BSD 3-C"
  },
  {
    "path": "vendor/github.com/PagerDuty/godspeed/godspeed.go",
    "chars": 4009,
    "preview": "// Copyright 2014-2015 PagerDuty, Inc, et al. All rights reserved.\n// Use of this source code is governed by the BSD 3-C"
  },
  {
    "path": "vendor/github.com/PagerDuty/godspeed/service_checks.go",
    "chars": 1914,
    "preview": "// Copyright 2014-2015 PagerDuty, Inc, et al. All rights reserved.\n// Use of this source code is governed by the BSD 3-C"
  },
  {
    "path": "vendor/github.com/PagerDuty/godspeed/shared.go",
    "chars": 1070,
    "preview": "// Copyright 2014-2015 PagerDuty, Inc, et al. All rights reserved.\n// Use of this source code is governed by the BSD 3-C"
  },
  {
    "path": "vendor/github.com/PagerDuty/godspeed/stats.go",
    "chars": 3640,
    "preview": "// Copyright 2014-2015 PagerDuty, Inc, et al. All rights reserved.\n// Use of this source code is governed by the BSD 3-C"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/.gitignore",
    "chars": 11,
    "preview": "*~\nh2i/h2i\n"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/AUTHORS",
    "chars": 887,
    "preview": "# This file is like Go's AUTHORS file: it lists Copyright holders.\n# The list of humans who have contributd is in the CO"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/CONTRIBUTORS",
    "chars": 935,
    "preview": "# This file is like Go's CONTRIBUTORS file: it lists humans.\n# The list of copyright holders (which may be companies) ar"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/Dockerfile",
    "chars": 1149,
    "preview": "#\n# This Dockerfile builds a recent curl with HTTP/2 client support, using\n# a recent nghttp2 build.\n#\n# See the Makefil"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/HACKING",
    "chars": 193,
    "preview": "We only accept contributions from users who have gone through Go's\ncontribution process (signed a CLA).\n\nPlease acknowle"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/LICENSE",
    "chars": 202,
    "preview": "Copyright 2014 Google & the Go AUTHORS\n\nGo AUTHORS are:\nSee https://code.google.com/p/go/source/browse/AUTHORS\n\nLicensed"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/Makefile",
    "chars": 44,
    "preview": "curlimage:\n\tdocker build -t gohttp2/curl .\n\n"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/README",
    "chars": 512,
    "preview": "This is a work-in-progress HTTP/2 implementation for Go.\n\nIt will eventually live in the Go standard library and won't r"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/buffer.go",
    "chars": 1777,
    "preview": "// Copyright 2014 The Go Authors.\n// See https://code.google.com/p/go/source/browse/CONTRIBUTORS\n// Licensed under the s"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/errors.go",
    "chars": 2662,
    "preview": "// Copyright 2014 The Go Authors.\n// See https://code.google.com/p/go/source/browse/CONTRIBUTORS\n// Licensed under the s"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/flow.go",
    "chars": 1147,
    "preview": "// Copyright 2014 The Go Authors.\n// See https://code.google.com/p/go/source/browse/CONTRIBUTORS\n// Licensed under the s"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/frame.go",
    "chars": 31472,
    "preview": "// Copyright 2014 The Go Authors.\n// See https://code.google.com/p/go/source/browse/CONTRIBUTORS\n// Licensed under the s"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/gotrack.go",
    "chars": 3324,
    "preview": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/github.com/bradfitz/http2/h2i/README.md",
    "chars": 2452,
    "preview": "# h2i\n\n**h2i** is an interactive HTTP/2 (\"h2\") console debugger. Miss the good ol'\ndays of telnetting to your HTTP/1.n s"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/h2i/h2i.go",
    "chars": 11829,
    "preview": "// Copyright 2015 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/github.com/bradfitz/http2/headermap.go",
    "chars": 1595,
    "preview": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/github.com/bradfitz/http2/hpack/encode.go",
    "chars": 7335,
    "preview": "// Copyright 2014 The Go Authors.\n// See https://code.google.com/p/go/source/browse/CONTRIBUTORS\n// Licensed under the s"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/hpack/hpack.go",
    "chars": 11570,
    "preview": "// Copyright 2014 The Go Authors.\n// See https://code.google.com/p/go/source/browse/CONTRIBUTORS\n// Licensed under the s"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/hpack/huffman.go",
    "chars": 3608,
    "preview": "// Copyright 2014 The Go Authors.\n// See https://code.google.com/p/go/source/browse/CONTRIBUTORS\n// Licensed under the s"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/hpack/tables.go",
    "chars": 5595,
    "preview": "// Copyright 2014 The Go Authors.\n// See https://code.google.com/p/go/source/browse/CONTRIBUTORS\n// Licensed under the s"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/http2.go",
    "chars": 6184,
    "preview": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/github.com/bradfitz/http2/pipe.go",
    "chars": 906,
    "preview": "// Copyright 2014 The Go Authors.\n// See https://code.google.com/p/go/source/browse/CONTRIBUTORS\n// Licensed under the s"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/server.go",
    "chars": 54194,
    "preview": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/github.com/bradfitz/http2/transport.go",
    "chars": 13179,
    "preview": "// Copyright 2015 The Go Authors.\n// See https://go.googlesource.com/go/+/master/CONTRIBUTORS\n// Licensed under the same"
  },
  {
    "path": "vendor/github.com/bradfitz/http2/write.go",
    "chars": 5368,
    "preview": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/github.com/bradfitz/http2/writesched.go",
    "chars": 7578,
    "preview": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/github.com/golang/glog/LICENSE",
    "chars": 10273,
    "preview": "Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AN"
  },
  {
    "path": "vendor/github.com/golang/glog/README",
    "chars": 1369,
    "preview": "glog\n====\n\nLeveled execution logs for Go.\n\nThis is an efficient pure Go implementation of leveled logs in the\nmanner of "
  },
  {
    "path": "vendor/github.com/golang/glog/glog.go",
    "chars": 36277,
    "preview": "// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/\n//\n// Copyright 2013 Google Inc. All"
  },
  {
    "path": "vendor/github.com/golang/glog/glog_file.go",
    "chars": 3323,
    "preview": "// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/\n//\n// Copyright 2013 Google Inc. All"
  },
  {
    "path": "vendor/github.com/golang/protobuf/LICENSE",
    "chars": 1583,
    "preview": "Go support for Protocol Buffers - Google's data interchange format\n\nCopyright 2010 The Go Authors.  All rights reserved."
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/Makefile",
    "chars": 1869,
    "preview": "# Go support for Protocol Buffers - Google's data interchange format\n#\n# Copyright 2010 The Go Authors.  All rights rese"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/clone.go",
    "chars": 5873,
    "preview": "// Go support for Protocol Buffers - Google's data interchange format\n//\n// Copyright 2011 The Go Authors.  All rights r"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/decode.go",
    "chars": 21785,
    "preview": "// Go support for Protocol Buffers - Google's data interchange format\n//\n// Copyright 2010 The Go Authors.  All rights r"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/encode.go",
    "chars": 32759,
    "preview": "// Go support for Protocol Buffers - Google's data interchange format\n//\n// Copyright 2010 The Go Authors.  All rights r"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/equal.go",
    "chars": 7100,
    "preview": "// Go support for Protocol Buffers - Google's data interchange format\n//\n// Copyright 2011 The Go Authors.  All rights r"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/extensions.go",
    "chars": 12972,
    "preview": "// Go support for Protocol Buffers - Google's data interchange format\n//\n// Copyright 2010 The Go Authors.  All rights r"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/lib.go",
    "chars": 21440,
    "preview": "// Go support for Protocol Buffers - Google's data interchange format\n//\n// Copyright 2010 The Go Authors.  All rights r"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/message_set.go",
    "chars": 8722,
    "preview": "// Go support for Protocol Buffers - Google's data interchange format\n//\n// Copyright 2010 The Go Authors.  All rights r"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/pointer_reflect.go",
    "chars": 13674,
    "preview": "// Go support for Protocol Buffers - Google's data interchange format\n//\n// Copyright 2012 The Go Authors.  All rights r"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/pointer_unsafe.go",
    "chars": 9331,
    "preview": "// Go support for Protocol Buffers - Google's data interchange format\n//\n// Copyright 2012 The Go Authors.  All rights r"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/properties.go",
    "chars": 21617,
    "preview": "// Go support for Protocol Buffers - Google's data interchange format\n//\n// Copyright 2010 The Go Authors.  All rights r"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.pb.go",
    "chars": 4101,
    "preview": "// Code generated by protoc-gen-go.\n// source: proto3_proto/proto3.proto\n// DO NOT EDIT!\n\n/*\nPackage proto3_proto is a g"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/proto3_proto/proto3.proto",
    "chars": 2301,
    "preview": "// Go support for Protocol Buffers - Google's data interchange format\n//\n// Copyright 2014 The Go Authors.  All rights r"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/text.go",
    "chars": 18986,
    "preview": "// Go support for Protocol Buffers - Google's data interchange format\n//\n// Copyright 2010 The Go Authors.  All rights r"
  },
  {
    "path": "vendor/github.com/golang/protobuf/proto/text_parser.go",
    "chars": 19072,
    "preview": "// Go support for Protocol Buffers - Google's data interchange format\n//\n// Copyright 2010 The Go Authors.  All rights r"
  },
  {
    "path": "vendor/github.com/gorilla/context/.travis.yml",
    "chars": 66,
    "preview": "language: go\n\ngo:\n  - 1.0\n  - 1.1\n  - 1.2\n  - 1.3\n  - 1.4\n  - tip\n"
  },
  {
    "path": "vendor/github.com/gorilla/context/LICENSE",
    "chars": 1476,
    "preview": "Copyright (c) 2012 Rodrigo Moraes. All rights reserved.\n\nRedistribution and use in source and binary forms, with or with"
  },
  {
    "path": "vendor/github.com/gorilla/context/README.md",
    "chars": 284,
    "preview": "context\n=======\n[![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla"
  },
  {
    "path": "vendor/github.com/gorilla/context/context.go",
    "chars": 3583,
    "preview": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lic"
  },
  {
    "path": "vendor/github.com/gorilla/context/doc.go",
    "chars": 2470,
    "preview": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lic"
  },
  {
    "path": "vendor/github.com/gorilla/mux/.travis.yml",
    "chars": 50,
    "preview": "language: go\n\ngo:\n  - 1.0\n  - 1.1\n  - 1.2\n  - tip\n"
  },
  {
    "path": "vendor/github.com/gorilla/mux/LICENSE",
    "chars": 1476,
    "preview": "Copyright (c) 2012 Rodrigo Moraes. All rights reserved.\n\nRedistribution and use in source and binary forms, with or with"
  },
  {
    "path": "vendor/github.com/gorilla/mux/README.md",
    "chars": 241,
    "preview": "mux\n===\n[![Build Status](https://travis-ci.org/gorilla/mux.png?branch=master)](https://travis-ci.org/gorilla/mux)\n\ngoril"
  },
  {
    "path": "vendor/github.com/gorilla/mux/doc.go",
    "chars": 6940,
    "preview": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lic"
  },
  {
    "path": "vendor/github.com/gorilla/mux/mux.go",
    "chars": 10227,
    "preview": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lic"
  },
  {
    "path": "vendor/github.com/gorilla/mux/regexp.go",
    "chars": 7323,
    "preview": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lic"
  },
  {
    "path": "vendor/github.com/gorilla/mux/route.go",
    "chars": 16248,
    "preview": "// Copyright 2012 The Gorilla Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lic"
  },
  {
    "path": "vendor/github.com/mitchellh/goamz/LICENSE",
    "chars": 8747,
    "preview": "This software is licensed under the LGPLv3, included below.\n\nAs a special exception to the GNU Lesser General Public Lic"
  },
  {
    "path": "vendor/github.com/mitchellh/goamz/aws/attempt.go",
    "chars": 1716,
    "preview": "package aws\n\nimport (\n\t\"time\"\n)\n\n// AttemptStrategy represents a strategy for waiting for an action\n// to complete succe"
  },
  {
    "path": "vendor/github.com/mitchellh/goamz/aws/aws.go",
    "chars": 11597,
    "preview": "//\n// goamz - Go packages to interact with the Amazon Web Services.\n//\n//   https://wiki.ubuntu.com/goamz\n//\n// Copyrigh"
  },
  {
    "path": "vendor/github.com/mitchellh/goamz/aws/client.go",
    "chars": 3068,
    "preview": "package aws\n\nimport (\n\t\"math\"\n\t\"net\"\n\t\"net/http\"\n\t\"time\"\n)\n\ntype RetryableFunc func(*http.Request, *http.Response, error"
  },
  {
    "path": "vendor/github.com/mitchellh/goamz/s3/multi.go",
    "chars": 11103,
    "preview": "package s3\n\nimport (\n\t\"bytes\"\n\t\"crypto/md5\"\n\t\"encoding/base64\"\n\t\"encoding/hex\"\n\t\"encoding/xml\"\n\t\"errors\"\n\t\"io\"\n\t\"sort\"\n\t"
  },
  {
    "path": "vendor/github.com/mitchellh/goamz/s3/s3.go",
    "chars": 21538,
    "preview": "//\n// goamz - Go packages to interact with the Amazon Web Services.\n//\n//   https://wiki.ubuntu.com/goamz\n//\n// Copyrigh"
  },
  {
    "path": "vendor/github.com/mitchellh/goamz/s3/s3test/server.go",
    "chars": 16714,
    "preview": "package s3test\n\nimport (\n\t\"bytes\"\n\t\"crypto/md5\"\n\t\"encoding/hex\"\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"github.com/mitchellh/goamz/s3\"\n"
  },
  {
    "path": "vendor/github.com/mitchellh/goamz/s3/sign.go",
    "chars": 3133,
    "preview": "package s3\n\nimport (\n\t\"crypto/hmac\"\n\t\"crypto/sha1\"\n\t\"encoding/base64\"\n\t\"log\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/mitchellh/"
  },
  {
    "path": "vendor/github.com/trustmaster/go-aspell/README.md",
    "chars": 3012,
    "preview": "# Aspell library bindings for Go\n\nGNU Aspell is a spell checking tool written in C/C++. This package provides simplified"
  },
  {
    "path": "vendor/github.com/trustmaster/go-aspell/aspell.go",
    "chars": 5839,
    "preview": "// Package aspell provides simplified bindings to GNU Aspell spell checking library.\npackage aspell\n\n/*\n#cgo LDFLAGS: -l"
  },
  {
    "path": "vendor/github.com/vaughan0/go-ini/LICENSE",
    "chars": 1058,
    "preview": "Copyright (c) 2013 Vaughan Newton\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this "
  },
  {
    "path": "vendor/github.com/vaughan0/go-ini/README.md",
    "chars": 1180,
    "preview": "go-ini\n======\n\nINI parsing library for Go (golang).\n\nView the API documentation [here](http://godoc.org/github.com/vaugh"
  },
  {
    "path": "vendor/github.com/vaughan0/go-ini/ini.go",
    "chars": 2908,
    "preview": "// Package ini provides functions for parsing INI configuration files.\npackage ini\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\""
  },
  {
    "path": "vendor/github.com/vaughan0/go-ini/test.ini",
    "chars": 25,
    "preview": "[default]\nstuff = things\n"
  },
  {
    "path": "vendor/golang.org/x/crypto/LICENSE",
    "chars": 1479,
    "preview": "Copyright (c) 2009 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or with"
  },
  {
    "path": "vendor/golang.org/x/crypto/PATENTS",
    "chars": 1303,
    "preview": "Additional IP Rights Grant (Patents)\n\n\"This implementation\" means the copyrightable works distributed by\nGoogle as part "
  },
  {
    "path": "vendor/golang.org/x/crypto/ssh/terminal/terminal.go",
    "chars": 20992,
    "preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/crypto/ssh/terminal/util.go",
    "chars": 3980,
    "preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go",
    "chars": 332,
    "preview": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/crypto/ssh/terminal/util_linux.go",
    "chars": 457,
    "preview": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/crypto/ssh/terminal/util_windows.go",
    "chars": 4423,
    "preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/net/LICENSE",
    "chars": 1479,
    "preview": "Copyright (c) 2009 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or with"
  },
  {
    "path": "vendor/golang.org/x/net/PATENTS",
    "chars": 1303,
    "preview": "Additional IP Rights Grant (Patents)\n\n\"This implementation\" means the copyrightable works distributed by\nGoogle as part "
  },
  {
    "path": "vendor/golang.org/x/net/context/context.go",
    "chars": 14094,
    "preview": "// Copyright 2014 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
  },
  {
    "path": "vendor/golang.org/x/oauth2/.travis.yml",
    "chars": 270,
    "preview": "language: go\n\ngo:\n  - 1.3\n  - 1.4\n\ninstall:\n  - export GOPATH=\"$HOME/gopath\"\n  - mkdir -p \"$GOPATH/src/golang.org/x\"\n  -"
  },
  {
    "path": "vendor/golang.org/x/oauth2/AUTHORS",
    "chars": 173,
    "preview": "# This source code refers to The Go Authors for copyright purposes.\n# The master list of authors is in the main Go distr"
  },
  {
    "path": "vendor/golang.org/x/oauth2/CONTRIBUTING.md",
    "chars": 1042,
    "preview": "# Contributing to Go\n\nGo is an open source project.\n\nIt is the work of hundreds of contributors. We appreciate your help"
  },
  {
    "path": "vendor/golang.org/x/oauth2/CONTRIBUTORS",
    "chars": 170,
    "preview": "# This source code was written by the Go contributors.\n# The master list of contributors is in the main Go distribution,"
  },
  {
    "path": "vendor/golang.org/x/oauth2/LICENSE",
    "chars": 1483,
    "preview": "Copyright (c) 2009 The oauth2 Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or "
  },
  {
    "path": "vendor/golang.org/x/oauth2/README.md",
    "chars": 2069,
    "preview": "# OAuth2 for Go\n\n[![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/o"
  },
  {
    "path": "vendor/golang.org/x/oauth2/client_appengine.go",
    "chars": 546,
    "preview": "// Copyright 2014 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/clientcredentials/clientcredentials.go",
    "chars": 3605,
    "preview": "// Copyright 2014 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/facebook/facebook.go",
    "chars": 485,
    "preview": "// Copyright 2015 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/github/github.go",
    "chars": 478,
    "preview": "// Copyright 2014 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/google/appengine.go",
    "chars": 2153,
    "preview": "// Copyright 2014 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/google/appengine_hook.go",
    "chars": 311,
    "preview": "// Copyright 2015 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/google/default.go",
    "chars": 4822,
    "preview": "// Copyright 2015 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/google/google.go",
    "chars": 4821,
    "preview": "// Copyright 2014 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/google/sdk.go",
    "chars": 5283,
    "preview": "// Copyright 2015 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/internal/oauth2.go",
    "chars": 2057,
    "preview": "// Copyright 2014 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/internal/token.go",
    "chars": 6437,
    "preview": "// Copyright 2014 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/internal/transport.go",
    "chars": 2039,
    "preview": "// Copyright 2014 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/jws/jws.go",
    "chars": 4679,
    "preview": "// Copyright 2014 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/jwt/jwt.go",
    "chars": 4495,
    "preview": "// Copyright 2014 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/linkedin/linkedin.go",
    "chars": 499,
    "preview": "// Copyright 2015 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/oauth2.go",
    "chars": 10602,
    "preview": "// Copyright 2014 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/odnoklassniki/odnoklassniki.go",
    "chars": 510,
    "preview": "// Copyright 2015 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/paypal/paypal.go",
    "chars": 864,
    "preview": "// Copyright 2015 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/token.go",
    "chars": 4179,
    "preview": "// Copyright 2014 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/transport.go",
    "chars": 3091,
    "preview": "// Copyright 2014 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/golang.org/x/oauth2/vk/vk.go",
    "chars": 446,
    "preview": "// Copyright 2015 The oauth2 Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// lice"
  },
  {
    "path": "vendor/google.golang.org/api/LICENSE",
    "chars": 1475,
    "preview": "Copyright (c) 2011 Google Inc. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\n"
  },
  {
    "path": "vendor/google.golang.org/api/bigquery/v2/bigquery-api.json",
    "chars": 80562,
    "preview": "{\n \"kind\": \"discovery#restDescription\",\n \"etag\": \"\\\"ye6orv2F-1npMW3u9suM3a7C5Bo/n2LVhGPabQO3DmbKxkomJprJEEo\\\"\",\n \"discov"
  },
  {
    "path": "vendor/google.golang.org/api/bigquery/v2/bigquery-gen.go",
    "chars": 119661,
    "preview": "// Package bigquery provides access to the BigQuery API.\n//\n// See https://cloud.google.com/bigquery/\n//\n// Usage exampl"
  },
  {
    "path": "vendor/google.golang.org/api/container/v1beta1/container-api.json",
    "chars": 21070,
    "preview": "{\n \"kind\": \"discovery#restDescription\",\n \"etag\": \"\\\"ye6orv2F-1npMW3u9suM3a7C5Bo/ReRXGEgk9TcyLgT1qFhzuzuEb7E\\\"\",\n \"discov"
  },
  {
    "path": "vendor/google.golang.org/api/container/v1beta1/container-gen.go",
    "chars": 33818,
    "preview": "// Package container provides access to the Google Container Engine API.\n//\n// See https://cloud.google.com/container-en"
  },
  {
    "path": "vendor/google.golang.org/api/googleapi/googleapi.go",
    "chars": 16094,
    "preview": "// Copyright 2011 Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that"
  },
  {
    "path": "vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE",
    "chars": 1057,
    "preview": "Copyright (c) 2013 Joshua Tacoma\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis s"
  },
  {
    "path": "vendor/google.golang.org/api/googleapi/internal/uritemplates/uritemplates.go",
    "chars": 8500,
    "preview": "// Copyright 2013 Joshua Tacoma. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license t"
  },
  {
    "path": "vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go",
    "chars": 287,
    "preview": "package uritemplates\n\nfunc Expand(path string, expansions map[string]string) (string, error) {\n\ttemplate, err := Parse(p"
  },
  {
    "path": "vendor/google.golang.org/api/googleapi/transport/apikey.go",
    "chars": 1024,
    "preview": "// Copyright 2012 Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that"
  },
  {
    "path": "vendor/google.golang.org/api/googleapi/types.go",
    "chars": 3329,
    "preview": "// Copyright 2013 Google Inc. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license that"
  },
  {
    "path": "vendor/google.golang.org/api/pubsub/v1beta2/pubsub-api.json",
    "chars": 17838,
    "preview": "{\n \"kind\": \"discovery#restDescription\",\n \"etag\": \"\\\"ye6orv2F-1npMW3u9suM3a7C5Bo/k747AQVNKzUoa08QT-Z1GxOMZC0\\\"\",\n \"discov"
  },
  {
    "path": "vendor/google.golang.org/api/pubsub/v1beta2/pubsub-gen.go",
    "chars": 43494,
    "preview": "// Package pubsub provides access to the Google Cloud Pub/Sub API.\n//\n// Usage example:\n//\n//   import \"google.golang.or"
  },
  {
    "path": "vendor/google.golang.org/api/storage/v1/storage-api.json",
    "chars": 93157,
    "preview": "{\n \"kind\": \"discovery#restDescription\",\n \"etag\": \"\\\"ye6orv2F-1npMW3u9suM3a7C5Bo/lTxRjj5-AURGfd9glUYk42wgbOA\\\"\",\n \"discov"
  },
  {
    "path": "vendor/google.golang.org/api/storage/v1/storage-gen.go",
    "chars": 210353,
    "preview": "// Package storage provides access to the Cloud Storage API.\n//\n// See https://developers.google.com/storage/docs/json_a"
  },
  {
    "path": "vendor/google.golang.org/appengine/.travis.yml",
    "chars": 523,
    "preview": "language: go\nsudo: false\n\ngo:\n  - 1.4\n\ninstall:\n  - go get -v -t -d google.golang.org/appengine/...\n  - mkdir sdk\n  - cu"
  },
  {
    "path": "vendor/google.golang.org/appengine/LICENSE",
    "chars": 11358,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "vendor/google.golang.org/appengine/README.md",
    "chars": 3537,
    "preview": "# Go App Engine packages\n\n[![Build Status](https://travis-ci.org/golang/appengine.svg)](https://travis-ci.org/golang/app"
  },
  {
    "path": "vendor/google.golang.org/appengine/aetest/doc.go",
    "chars": 921,
    "preview": "/*\nPackage aetest provides an API for running dev_appserver for use in tests.\n\nAn example test file:\n\n\tpackage foo_test\n"
  },
  {
    "path": "vendor/google.golang.org/appengine/aetest/instance.go",
    "chars": 1585,
    "preview": "package aetest\n\nimport (\n\t\"io\"\n\t\"net/http\"\n\n\t\"golang.org/x/net/context\"\n\t\"google.golang.org/appengine\"\n)\n\n// Instance re"
  },
  {
    "path": "vendor/google.golang.org/appengine/aetest/instance_classic.go",
    "chars": 587,
    "preview": "// +build appengine\n\npackage aetest\n\nimport \"appengine/aetest\"\n\n// NewInstance launches a running instance of api_server"
  },
  {
    "path": "vendor/google.golang.org/appengine/aetest/instance_vm.go",
    "chars": 6245,
    "preview": "// +build !appengine\n\npackage aetest\n\nimport (\n\t\"bufio\"\n\t\"crypto/rand\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t"
  },
  {
    "path": "vendor/google.golang.org/appengine/aetest/user.go",
    "chars": 1057,
    "preview": "package aetest\n\nimport (\n\t\"hash/crc32\"\n\t\"net/http\"\n\t\"strconv\"\n\n\t\"google.golang.org/appengine/user\"\n)\n\n// Login causes th"
  },
  {
    "path": "vendor/google.golang.org/appengine/appengine.go",
    "chars": 2611,
    "preview": "// Copyright 2011 Google Inc. All rights reserved.\n// Use of this source code is governed by the Apache 2.0\n// license t"
  },
  {
    "path": "vendor/google.golang.org/appengine/appengine_vm.go",
    "chars": 1602,
    "preview": "// Copyright 2015 Google Inc. All rights reserved.\n// Use of this source code is governed by the Apache 2.0\n// license t"
  },
  {
    "path": "vendor/google.golang.org/appengine/blobstore/blobstore.go",
    "chars": 8784,
    "preview": "// Copyright 2011 Google Inc. All rights reserved.\n// Use of this source code is governed by the Apache 2.0\n// license t"
  },
  {
    "path": "vendor/google.golang.org/appengine/blobstore/read.go",
    "chars": 3992,
    "preview": "// Copyright 2012 Google Inc. All rights reserved.\n// Use of this source code is governed by the Apache 2.0\n// license t"
  },
  {
    "path": "vendor/google.golang.org/appengine/capability/capability.go",
    "chars": 1562,
    "preview": "// Copyright 2011 Google Inc. All rights reserved.\n// Use of this source code is governed by the Apache 2.0\n// license t"
  },
  {
    "path": "vendor/google.golang.org/appengine/channel/channel.go",
    "chars": 2375,
    "preview": "// Copyright 2011 Google Inc. All rights reserved.\n// Use of this source code is governed by the Apache 2.0\n// license t"
  },
  {
    "path": "vendor/google.golang.org/appengine/cloudsql/cloudsql.go",
    "chars": 1812,
    "preview": "// Copyright 2013 Google Inc. All rights reserved.\n// Use of this source code is governed by the Apache 2.0\n// license t"
  },
  {
    "path": "vendor/google.golang.org/appengine/cloudsql/cloudsql_classic.go",
    "chars": 324,
    "preview": "// Copyright 2013 Google Inc. All rights reserved.\n// Use of this source code is governed by the Apache 2.0\n// license t"
  },
  {
    "path": "vendor/google.golang.org/appengine/cloudsql/cloudsql_vm.go",
    "chars": 346,
    "preview": "// Copyright 2013 Google Inc. All rights reserved.\n// Use of this source code is governed by the Apache 2.0\n// license t"
  },
  {
    "path": "vendor/google.golang.org/appengine/cmd/aebundler/aebundler.go",
    "chars": 9067,
    "preview": "// Copyright 2015 Google Inc. All rights reserved.\n// Use of this source code is governed by the Apache 2.0\n// license t"
  },
  {
    "path": "vendor/google.golang.org/appengine/cmd/aedeploy/aedeploy.go",
    "chars": 7108,
    "preview": "// Copyright 2015 Google Inc. All rights reserved.\n// Use of this source code is governed by the Apache 2.0\n// license t"
  },
  {
    "path": "vendor/google.golang.org/appengine/datastore/datastore.go",
    "chars": 11802,
    "preview": "// Copyright 2011 Google Inc. All rights reserved.\n// Use of this source code is governed by the Apache 2.0\n// license t"
  }
]

// ... and 224 more files (download for full content)

About this extraction

This page contains the full source code of the gophergala/ImgurGo GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 424 files (3.0 MB), approximately 820.2k tokens, and a symbol index with 8322 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!