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  [](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.
[](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
[](https://travis-ci.org/PagerDuty/godspeed)
[](https://godoc.org/github.com/PagerDuty/godspeed)
[](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
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
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  [\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[](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[](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[](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[](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[](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.