<commit_before>/*
See LICENSE file for license details
Copyright (c) 2015 XOR Data Exchange, Inc.

Superdog - the Crypto library for Vault from Hashicorp

Superdog is a library for managing strong cryptography in both development and test environments.  Superdog provides an elegant wrapper to the Vault(https://www.vaultproject.io) API that allows you to manage your cryptographic keys in Vault using any code that implements the `KeyProvider` interface.  An implemention of the `KeyProvider` interface is provided for Vault, but others could be supported.

Features

-  Versioned Keys - Key version is stored as the first few bytes of the encrypted text
-  Key Rotation - Rotate your keys safely, knowing that you'll always be able to decrypt older versionss
-  Development implementation for tests and local development
-  Versioned and Rotated IV/Salt - `SaltProvider` interface works the same as `KeyProvider` to allow development and testing access to the crypto libraries without requiring a live Key (Vault) server
-  `Reencrypt` function to simplify key rotation, decrypts with given key, reencrypts with latest key

Cypher Suites

`superdog` supports AES encryption with CFB/CTR/GCM/OFB modes.

Production Usage
By default, `superdog` uses the `DevKeyProvider` which is a static key with static IV.  This is extremely insecure, and SHOULD NOT ever be used in production.

We reccommend using Go's [build tags](https://golang.org/pkg/go/build/) to enable strong cryptography in production usage.

Create a file with your connection routines in the init() function.  Add the build tag `// +build production` to the top of that file.

	// +build production

	package main
	import (
		"github.com/xordataexchange/superdog"
		"github.com/xordataexxchange/superdog/vault/hashi"
		"github.com/hashicorp/vault/api"
	)

	// Assign each application a unique UUID
	// and use Vault's AppID authentication mechanism
	const (
		appid = "SOME RANDOM UUID"
	)

	func init() {
		user := os.Getenv("VAULT_USER")
		vaultaddr := os.Getenv("VAULT_ADDRESS")
		// TEST these for empty strings & handle appropriately in your code
		cfg:= api.DefaultConfig()
		cfg.Address = vaultaddr
		vault, err := hashi.NewVault(cfg)
		if err != nil {
			// handle appropriately
		}
		err = vault.AuthAppID(appid, user)
		if err != nil {
			// handle appropriately
		}
		crypto.DefaultKeyProvider = vault
		crypto.DefaultSaltProvider = vault
	}

Now compile your program with `go build -tags production` to include this code.  The `KeyProvider` will be set to use Vault.

*/
package superdog
<commit_msg>examples and godoc<commit_after>/*
See LICENSE file for license details
Copyright (c) 2015 XOR Data Exchange, Inc.

Superdog - the Crypto library for Vault from Hashicorp

Superdog is a library for managing strong cryptography in both development and test environments.  Superdog provides an elegant wrapper to the Vault(https://www.vaultproject.io) API that allows you to manage your cryptographic keys in Vault using any code that implements the `KeyProvider` interface.  An implemention of the `KeyProvider` interface is provided for Vault, but others could be supported.

Features

-  Versioned Keys - Key version is stored as the first few bytes of the encrypted text
-  Key Rotation - Rotate your keys safely, knowing that you'll always be able to decrypt older versionss
-  Development implementation for tests and local development
-  Versioned and Rotated IV/Salt - `SaltProvider` interface works the same as `KeyProvider` to allow development and testing access to the crypto libraries without requiring a live Key (Vault) server
-  `Reencrypt` function to simplify key rotation, decrypts with given key, reencrypts with latest key

Cypher Suites

`superdog` supports AES encryption with CFB/CTR/GCM/OFB modes.

Production Usage
By default, `superdog` uses the `DevKeyProvider` which is a static key with static IV.  This is extremely insecure, and SHOULD NOT ever be used in production.

We reccommend using Go's [build tags](https://golang.org/pkg/go/build/) to enable strong cryptography in production usage.

Create a file with your connection routines in the init() function.  Add the build tag `// +build production` to the top of that file.  Incomplete example:

	// +build production

	package main
	import (
		"github.com/xordataexchange/superdog"
		"github.com/xordataexxchange/superdog/vault/hashi"
		"github.com/hashicorp/vault/api"
	)

	// Assign each application a unique UUID
	// and use Vault's AppID authentication mechanism
	const (
		appid = "SOME RANDOM UUID"
	)

	func init() {
		user := os.Getenv("VAULT_USER")
		vaultaddr := os.Getenv("VAULT_ADDRESS")
		// TEST these for empty strings & handle appropriately in your code
		cfg:= api.DefaultConfig()
		cfg.Address = vaultaddr
		vault, err := hashi.NewVault(cfg)
		if err != nil {
			// handle appropriately
		}
		err = vault.AuthAppID(appid, user)
		if err != nil {
			// handle appropriately
		}
		crypto.DefaultKeyProvider = vault
		crypto.DefaultSaltProvider = vault
	}

Now compile your program with `go build -tags production` to include this code.  The `KeyProvider` will be set to use Vault.

*/
package superdog
<|endoftext|>


<commit_before>/*

Package saltpack is an implementation of the saltpack message format. Saltpack
is a light wrapper around Dan Berstein's famous NaCl library. It adds support
for longer messages, streaming input and output of data, multiple recipients
for encrypted messages, and a reasonable armoring format. We intend Saltpack
as a replacement for the PGP messaging format, as it can be used in many of
the same circumstances.  However, it is designed to be: (1) simpler; (2)
easier to implement; (3) judicious (perhaps judgmental) in its crypto usage;
(4) fully modern (no CBC option here); (5) high performance; (6) less bug-
prone; (7) generally unwilling to output unauthenticated data; and (8) easier
to compose with other software in any manner of languages or platforms.

Key Management

Saltpack makes no attempt to manage keys. We assume the wrapping application
has a story for key management.

Modes of Operation

Saltpack supports three modes of operation: encrypted messages, attached
signatures, and detached signatures. Encrypted messages use NaCl's
authenticated public-key encryption; we add repudiable authentication. An
attached signature contains a message and a signature that authenticates it. A
detached signature contains just the signature, and assumes an independent
delievery mechanism for the file (this might come up when distributing an ISO
and separate signature of the file).

Encoding

Saltpack has two encoding modes: binary and armored. In armored mode, saltpack
outputs in Base62-encoding, suitable for publication into any manner of Web
settings without fear of markup-caused mangling.

API

This saltpack library implementation supports two API patterns: streaming and
all-at-once. The former is useful for large files that can't fit into memory;
the latter is more convenient. Both produce the same output.

More Info

See https://saltpack.org

*/
package saltpack
<commit_msg>CBC -> CFB<commit_after>/*

Package saltpack is an implementation of the saltpack message format. Saltpack
is a light wrapper around Dan Berstein's famous NaCl library. It adds support
for longer messages, streaming input and output of data, multiple recipients
for encrypted messages, and a reasonable armoring format. We intend Saltpack
as a replacement for the PGP messaging format, as it can be used in many of
the same circumstances.  However, it is designed to be: (1) simpler; (2)
easier to implement; (3) judicious (perhaps judgmental) in its crypto usage;
(4) fully modern (no CFB mode here); (5) high performance; (6) less bug-
prone; (7) generally unwilling to output unauthenticated data; and (8) easier
to compose with other software in any manner of languages or platforms.

Key Management

Saltpack makes no attempt to manage keys. We assume the wrapping application
has a story for key management.

Modes of Operation

Saltpack supports three modes of operation: encrypted messages, attached
signatures, and detached signatures. Encrypted messages use NaCl's
authenticated public-key encryption; we add repudiable authentication. An
attached signature contains a message and a signature that authenticates it. A
detached signature contains just the signature, and assumes an independent
delievery mechanism for the file (this might come up when distributing an ISO
and separate signature of the file).

Encoding

Saltpack has two encoding modes: binary and armored. In armored mode, saltpack
outputs in Base62-encoding, suitable for publication into any manner of Web
settings without fear of markup-caused mangling.

API

This saltpack library implementation supports two API patterns: streaming and
all-at-once. The former is useful for large files that can't fit into memory;
the latter is more convenient. Both produce the same output.

More Info

See https://saltpack.org

*/
package saltpack
<|endoftext|>


<commit_before>// Package validator implements value validations
//
// Copyright 2014 Roberto Teixeira <robteix@robteix.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*
Package validator implements value validations based on struct tags.

In code it is often necessary to validate that a given value is valid before
using it for something. A typical example might be something like this.

	if age < 18 {
		return error.New("age cannot be under 18")
	}

This is a simple enough example, but it can get significantly more complex,
especially when dealing with structs.

	l := len(strings.Trim(s.Username))
	if l < 3 || l > 40  || !regexp.MatchString("^[a-zA-Z]$", s.Username) ||	s.Age < 18 || s.Password {
		return errors.New("Invalid request")
	}

You get the idea. Package validator allows one to define valid values as
struct tags when defining a new struct type.

	type NewUserRequest struct {
		Username string `validate:"min=3,max=40,regexp=^[a-zA-Z]$"`
		Name string     `validate:"nonzero"`
		Age int         `validate:"min=18"`
		Password string `validate:"min=8"`
	}

Then validating a variable of type NewUserRequest becomes trivial.

	nur := NewUserRequest{Username: "something", ...}
	if errs := validator.Validate(nur); errs != nil {
		// do something
	}

Builtin validator functions

Here is the list of validator functions builtin in the package.

	len
		For numeric numbers, len will simply make sure that the value is
		equal to the parameter given. For strings, it checks that
		the string length is exactly that number of characters. For slices,
		arrays, and maps, validates the number of items. (Usage: len=10)

	max
		For numeric numbers, max will simply make sure that the value is
		lesser or equal to the parameter given. For strings, it checks that
		the string length is at most that number of characters. For slices,
		arrays, and maps, validates the number of items. (Usage: max=10)

	min
		For numeric numbers, min will simply make sure that the value is
		greater or equal to the parameter given. For strings, it checks that
		the string length is at least that number of characters. For slices,
		arrays, and maps, validates the number of items. (Usage: min=10)

	nonzero
		This validates that the value is not zero. The appropriate zero value
		is given by the Go spec (e.g. for int it's 0, for string it's "", for
		pointers is nil, etc.) Usage: nonzero

	regexp
		Only valid for string types, it will validate that the value matches
		the regular expression provided as parameter. (Usage: regexp=^a.*b$)

Note that there are no tests to prevent conflicting validator parameters. For
instance, these fields will never be valid.

	...
	A int     `validate:"max=0,min=1"`
	B string  `validate:"len=10,regexp=^$"
	...

Custom validation functions

It is possible to define custom validation functions by using SetValidationFunc.
First, one needs to create a validation function.

	// Very simple validation func
	func notZZ(v interface{}, param string) error {
		st := reflect.ValueOf(v)
		if st.Kind() != reflect.String {
			return validate.ErrUnsupported
		}
		if st.String() == "ZZ" {
			return errors.New("value cannot be ZZ")
		}
		return nil
	}

Then one needs to add it to the list of validation funcs and give it a "tag" name.

	validate.SetValidationFunc("notzz", notZZ)

Then it is possible to use the notzz validation tag. This will print
"Field A error: value cannot be ZZ"

	type T struct {
		A string  `validate:"nonzero,notzz"`
	}
	t := T{"ZZ"}
	if errs := validator.Validate(t); errs != nil {
		fmt.Printf("Field A error: %s\n", errs["A"][0])
	}

To use parameters, it is very similar.

	// Very simple validator with parameter
	func notSomething(v interface{}, param string) error {
		st := reflect.ValueOf(v)
		if st.Kind() != reflect.String {
			return validate.ErrUnsupported
		}
		if st.String() == param {
			return errors.New("value cannot be " + param)
		}
		return nil
	}

And then the code below should print "Field A error: value cannot be ABC".

	validator.SetValidationFunc("notsomething", notSomething)
	type T struct {
		A string  `validate:"notsomething=ABC"`
	}
	t := T{"ABC"}
	if errs := validator.Validate(t); errs != nil {
		fmt.Printf("Field A error: %s\n", errs["A"][0])
	}

As well, it is possible to overwrite builtin validation functions.

	validate.SetValidationFunc("min", myMinFunc)

And you can delete a validation function by setting it to nil.

	validate.SetValidationFunc("notzz", nil)
	validate.SetValidationFunc("nonzero", nil)

Using a non-existing validation func in a field tag will always return
false and with error validate.ErrUnknownTag.

Finally, package validator also provides a helper function that can be used
to validate simple variables/values.

    	// errs: nil
	errs = validator.Valid(42, "min=10, max=50")

	// errs: [validate.ErrZeroValue]
	errs = validator.Valid(nil, "nonzero")

	// errs: [validate.ErrMin,validate.ErrMax]
	errs = validator.Valid("hi", "nonzero,min=3,max=2")

Custom tag name

In case there is a reason why one would not wish to use tag 'validate' (maybe due to
a conflict with a different package), it is possible to tell the package to use
a different tag.

	validator.SetTag("valid")

Then.

	Type T struct {
		A int    `valid:"min=8, max=10"`
		B string `valid:"nonzero"`
	}

SetTag is permanent. The new tag name will be used until it is again changed
with a new call to SetTag. A way to temporarily use a different tag exists.

	validator.WithTag("foo").Validate(t)
	validator.WithTag("bar").Validate(t)
	// But this will go back to using 'validate'
	validator.Validate(t)

Multiple validators

You may often need to have a different set of validation
rules for different situations. In all the examples above,
we only used the default validator but you could create a
new one and set specific rules for it.

For instance, you might use the same struct to decode incoming JSON for a REST API
but your needs will change when you're using it to, say, create a new instance
in storage vs. when you need to change something.

	type User struct {
		Username string `validate:"nonzero"`
		Name string     `validate:"nonzero"`
		Age int         `validate:"nonzero"`
		Password string `validate:"nonzero"`
	}

Maybe when creating a new user, you need to make sure all values in the struct are filled,
but then you use the same struct to handle incoming requests to, say, change the password,
in which case you only need the Username and the Password and don't care for the others.
You might use two different validators.

	type User struct {
		Username string `creating:"nonzero" chgpw:"nonzero"`
		Name string     `creating:"nonzero"`
		Age int         `creating:"nonzero"`
		Password string `creating:"nonzero" chgpw:"nonzero"`
	}

	var (
		creationValidator = validator.NewValidator()
		chgPwValidator = validator.NewValidator()
	)

	func init() {
		creationValidator.SetTag("creating")
		chgPwValidator.SetTag("chgpw")
	}

	...

	func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
		var u User
		json.NewDecoder(r.Body).Decode(&user)
		if errs := creationValidator.Validate(user); errs != nil {
			// the request did not include all of the User
			// struct fields, so send a http.StatusBadRequest
			// back or something
		}
		// create the new user
	}

	func SetNewUserPasswordHandler(w http.ResponseWriter, r *http.Request) {
		var u User
		json.NewDecoder(r.Body).Decode(&user)
		if errs := chgPwValidator.Validate(user); errs != nil {
			// the request did not Username and Password,
			// so send a http.StatusBadRequest
			// back or something
		}
		// save the new password
	}

It is also possible to do all of that using only the default validator as long
as SetTag is always called before calling validator.Validate() or you chain the
with WithTag().

*/
package validator
<commit_msg>Fix the regex example in the documentation.<commit_after>// Package validator implements value validations
//
// Copyright 2014 Roberto Teixeira <robteix@robteix.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*
Package validator implements value validations based on struct tags.

In code it is often necessary to validate that a given value is valid before
using it for something. A typical example might be something like this.

	if age < 18 {
		return error.New("age cannot be under 18")
	}

This is a simple enough example, but it can get significantly more complex,
especially when dealing with structs.

	l := len(strings.Trim(s.Username))
	if l < 3 || l > 40  || !regexp.MatchString("^[a-zA-Z]$", s.Username) ||	s.Age < 18 || s.Password {
		return errors.New("Invalid request")
	}

You get the idea. Package validator allows one to define valid values as
struct tags when defining a new struct type.

	type NewUserRequest struct {
		Username string `validate:"min=3,max=40,regexp=^[a-zA-Z]*$"`
		Name string     `validate:"nonzero"`
		Age int         `validate:"min=18"`
		Password string `validate:"min=8"`
	}

Then validating a variable of type NewUserRequest becomes trivial.

	nur := NewUserRequest{Username: "something", ...}
	if errs := validator.Validate(nur); errs != nil {
		// do something
	}

Builtin validator functions

Here is the list of validator functions builtin in the package.

	len
		For numeric numbers, len will simply make sure that the value is
		equal to the parameter given. For strings, it checks that
		the string length is exactly that number of characters. For slices,
		arrays, and maps, validates the number of items. (Usage: len=10)

	max
		For numeric numbers, max will simply make sure that the value is
		lesser or equal to the parameter given. For strings, it checks that
		the string length is at most that number of characters. For slices,
		arrays, and maps, validates the number of items. (Usage: max=10)

	min
		For numeric numbers, min will simply make sure that the value is
		greater or equal to the parameter given. For strings, it checks that
		the string length is at least that number of characters. For slices,
		arrays, and maps, validates the number of items. (Usage: min=10)

	nonzero
		This validates that the value is not zero. The appropriate zero value
		is given by the Go spec (e.g. for int it's 0, for string it's "", for
		pointers is nil, etc.) Usage: nonzero

	regexp
		Only valid for string types, it will validate that the value matches
		the regular expression provided as parameter. (Usage: regexp=^a.*b$)

Note that there are no tests to prevent conflicting validator parameters. For
instance, these fields will never be valid.

	...
	A int     `validate:"max=0,min=1"`
	B string  `validate:"len=10,regexp=^$"
	...

Custom validation functions

It is possible to define custom validation functions by using SetValidationFunc.
First, one needs to create a validation function.

	// Very simple validation func
	func notZZ(v interface{}, param string) error {
		st := reflect.ValueOf(v)
		if st.Kind() != reflect.String {
			return validate.ErrUnsupported
		}
		if st.String() == "ZZ" {
			return errors.New("value cannot be ZZ")
		}
		return nil
	}

Then one needs to add it to the list of validation funcs and give it a "tag" name.

	validate.SetValidationFunc("notzz", notZZ)

Then it is possible to use the notzz validation tag. This will print
"Field A error: value cannot be ZZ"

	type T struct {
		A string  `validate:"nonzero,notzz"`
	}
	t := T{"ZZ"}
	if errs := validator.Validate(t); errs != nil {
		fmt.Printf("Field A error: %s\n", errs["A"][0])
	}

To use parameters, it is very similar.

	// Very simple validator with parameter
	func notSomething(v interface{}, param string) error {
		st := reflect.ValueOf(v)
		if st.Kind() != reflect.String {
			return validate.ErrUnsupported
		}
		if st.String() == param {
			return errors.New("value cannot be " + param)
		}
		return nil
	}

And then the code below should print "Field A error: value cannot be ABC".

	validator.SetValidationFunc("notsomething", notSomething)
	type T struct {
		A string  `validate:"notsomething=ABC"`
	}
	t := T{"ABC"}
	if errs := validator.Validate(t); errs != nil {
		fmt.Printf("Field A error: %s\n", errs["A"][0])
	}

As well, it is possible to overwrite builtin validation functions.

	validate.SetValidationFunc("min", myMinFunc)

And you can delete a validation function by setting it to nil.

	validate.SetValidationFunc("notzz", nil)
	validate.SetValidationFunc("nonzero", nil)

Using a non-existing validation func in a field tag will always return
false and with error validate.ErrUnknownTag.

Finally, package validator also provides a helper function that can be used
to validate simple variables/values.

    	// errs: nil
	errs = validator.Valid(42, "min=10, max=50")

	// errs: [validate.ErrZeroValue]
	errs = validator.Valid(nil, "nonzero")

	// errs: [validate.ErrMin,validate.ErrMax]
	errs = validator.Valid("hi", "nonzero,min=3,max=2")

Custom tag name

In case there is a reason why one would not wish to use tag 'validate' (maybe due to
a conflict with a different package), it is possible to tell the package to use
a different tag.

	validator.SetTag("valid")

Then.

	Type T struct {
		A int    `valid:"min=8, max=10"`
		B string `valid:"nonzero"`
	}

SetTag is permanent. The new tag name will be used until it is again changed
with a new call to SetTag. A way to temporarily use a different tag exists.

	validator.WithTag("foo").Validate(t)
	validator.WithTag("bar").Validate(t)
	// But this will go back to using 'validate'
	validator.Validate(t)

Multiple validators

You may often need to have a different set of validation
rules for different situations. In all the examples above,
we only used the default validator but you could create a
new one and set specific rules for it.

For instance, you might use the same struct to decode incoming JSON for a REST API
but your needs will change when you're using it to, say, create a new instance
in storage vs. when you need to change something.

	type User struct {
		Username string `validate:"nonzero"`
		Name string     `validate:"nonzero"`
		Age int         `validate:"nonzero"`
		Password string `validate:"nonzero"`
	}

Maybe when creating a new user, you need to make sure all values in the struct are filled,
but then you use the same struct to handle incoming requests to, say, change the password,
in which case you only need the Username and the Password and don't care for the others.
You might use two different validators.

	type User struct {
		Username string `creating:"nonzero" chgpw:"nonzero"`
		Name string     `creating:"nonzero"`
		Age int         `creating:"nonzero"`
		Password string `creating:"nonzero" chgpw:"nonzero"`
	}

	var (
		creationValidator = validator.NewValidator()
		chgPwValidator = validator.NewValidator()
	)

	func init() {
		creationValidator.SetTag("creating")
		chgPwValidator.SetTag("chgpw")
	}

	...

	func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
		var u User
		json.NewDecoder(r.Body).Decode(&user)
		if errs := creationValidator.Validate(user); errs != nil {
			// the request did not include all of the User
			// struct fields, so send a http.StatusBadRequest
			// back or something
		}
		// create the new user
	}

	func SetNewUserPasswordHandler(w http.ResponseWriter, r *http.Request) {
		var u User
		json.NewDecoder(r.Body).Decode(&user)
		if errs := chgPwValidator.Validate(user); errs != nil {
			// the request did not Username and Password,
			// so send a http.StatusBadRequest
			// back or something
		}
		// save the new password
	}

It is also possible to do all of that using only the default validator as long
as SetTag is always called before calling validator.Validate() or you chain the
with WithTag().

*/
package validator
<|endoftext|>


<commit_before>// Package facebook implements Facebook Graph API.
//
// request token url is: https://www.facebook.com/dialog/oauth
// access token url is: https://graph.facebook.com/oauth/access_token
//
// These urls are hidden inside Graph struct as they don't change.
//
//     // Example
//     var graph := facebook.New(
//             "AppID",
//             "Secret",
//             "https://example.com/facebook/callback",
//             []string{"email"},
//     )
//
//     // Signup redirects user to facebook
//     func Signup(w http.ResponseWriter, r *http.Request) {
//             http.Redirect(w, r, graph.AuthURL(""), http.StatusFound)
//     }
//
//     // Handle response
//     func HandleOAuth(w http.ResponseWriter, r *http.Request) {
//             var g *facebook.Graph
//             g = graph
//             g.GetAccessToken(r)
//     }
//
package facebook
<commit_msg>fix documentation on tokens urls<commit_after>// Package facebook implements Facebook Graph API.
//
// Request token url is:
// - https://www.facebook.com/dialog/oauth
//
// access token url is:
// - https://graph.facebook.com/oauth/access_token
//
// These urls are hidden inside Graph struct as they don't change.
//
//     // Example
//     var graph := facebook.New(
//             "AppID",
//             "Secret",
//             "https://example.com/facebook/callback",
//             []string{"email"},
//     )
//
//     // Signup redirects user to facebook
//     func Signup(w http.ResponseWriter, r *http.Request) {
//             http.Redirect(w, r, graph.AuthURL(""), http.StatusFound)
//     }
//
//     // Handle response
//     func HandleOAuth(w http.ResponseWriter, r *http.Request) {
//             var g *facebook.Graph
//             g = graph
//             g.GetAccessToken(r)
//     }
//
package facebook
<|endoftext|>


<commit_before>/*
Package core is the perfect foundation for any web app as it's designed to have the best balance between readability, flexibility and performance.

It provides a pure handler (or "middleware") stack so you can perform actions downstream, then filter and manipulate the response upstream.

No handlers or helpers are bundled in the Core: it does one thing and does it well.
You can find official packages below.

For a complete documentation, see the Volatile website (http://volatile.whitedevops.com).
You can also read all the code (~100 LOC) within minutes.

Usage

Here is an example of a logger followed by the response writing:

	package main

	import (
		"fmt"
		"log"
		"time"

		"github.com/volatile/core"
	)

	func main() {
		// Log
		core.Use(func(c *core.Context) {
			start := time.Now()
			c.Next()
			log.Printf(" %s  %s  %s", c.Request.Method, c.Request.URL, time.Since(start))
		})

		// Response
		core.Use(func(c *core.Context) {
			fmt.Fprint(c.ResponseWriter, "Hello, World!")
		})

		core.Run()
	}

By default, your app is reachable at http://localhost:8080.

Use the -address parameter to set a custom listening address.
The value is saved in core.Address.

Use the -production parameter when serving in a production environment.
Some third-party handlers may have different behaviors depending on the environment.
The value is saved in core.Production.

Official handlers

These handlers are ready to be integrated in any of your app…

Compress — Clever response compressing — https://github.com/volatile/compress

CORS — Cross-Origin Resource Sharing support — https://github.com/volatile/cors

Log — Requests logging — https://github.com/volatile/log

Static — Simple assets serving — https://github.com/volatile/static

Others come…

Official helpers

Helpers provide syntactic sugar to ease repetitive code…

Response — Readable response helper — https://github.com/volatile/response

Route — Flexible routing helper — https://github.com/volatile/route

Others come…
*/
package core
<commit_msg>Fix GoDoc<commit_after>/*
Package core is the perfect foundation for any web app as it's designed to have the best balance between readability, flexibility and performance.

It provides a pure handler (or "middleware") stack so you can perform actions downstream, then filter and manipulate the response upstream.

No handlers or helpers are bundled in the Core: it does one thing and does it well.
You can find official packages below.

For a complete documentation, see the Volatile website (http://volatile.whitedevops.com).
You can also read all the code (~100 LOC) within minutes.

Usage

Example of a logger followed by the response writing:

	package main

	import (
		"fmt"
		"log"
		"time"

		"github.com/volatile/core"
	)

	func main() {
		// Log
		core.Use(func(c *core.Context) {
			start := time.Now()
			c.Next()
			log.Printf(" %s  %s  %s", c.Request.Method, c.Request.URL, time.Since(start))
		})

		// Response
		core.Use(func(c *core.Context) {
			fmt.Fprint(c.ResponseWriter, "Hello, World!")
		})

		core.Run()
	}

By default, your app is reachable at http://localhost:8080.

Use the -address parameter to set a custom listening address.
The value is saved in Address.

Use the -production parameter when serving in a production environment.
Some third-party handlers may have different behaviors depending on the environment.
The value is saved in Production.

Official handlers

These handlers are ready to be integrated in any of your app…

Compress — Clever response compressing — https://github.com/volatile/compress

CORS — Cross-Origin Resource Sharing support — https://github.com/volatile/cors

Log — Requests logging — https://github.com/volatile/log

Static — Simple assets serving — https://github.com/volatile/static

Others come…

Official helpers

Helpers provide syntactic sugar to ease repetitive code…

Response — Simple internationalization — https://github.com/volatile/i18n

Response — Readable response helper — https://github.com/volatile/response

Route — Flexible routing helper — https://github.com/volatile/route

Others come…
*/
package core
<|endoftext|>


<commit_before>// Copyright 2014 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

// Package mux 是一个实现了 http.Handler 的中间件，为用户提供了路由匹配等功能。
//
//  m := mux.New(false, false, nil, nil).
//          Get("/users/1", h).
//          Post("/login", h).
//          Get("/posts/{id:\\d+}", h).  // 正则路由
//          Options("/users/1", "GET")   // 手动指定 OPTIONS 请求的返回内容。
//
//  // 统一前缀路径的路由
//  p := m.Prefix("/api")
//  p.Get("/logout", h) // 相当于 m.Get("/api/logout", h)
//  p.Post("/login", h) // 相当于 m.Get("/api/login", h)
//
//  // 对同一资源的不同操作
//  res := p.Resource("/users/{id\\d+}")
//  res.Get(h)   // 相当于 m.Get("/api/users/{id}", h)
//  res.Post(h)  // 相当于 m.Post("/api/users/{id}", h)
//  res.URL(map[string]string{"id": "5"}, "") // /users/5
//
//  http.ListenAndServe(":8080", m)
//
//
//
// 正则表达式
//
// 路由中支持以正则表达式的方式进行匹配，表达式以大括号包含，内部以冒号分隔，
// 前半部分为变量的名称，后半部分为变量可匹配类型的正则表达式。比如：
//  /post/{id:\\d+} // 同上，但 id 的值只能为 \d+，\d+ 为正则表达式；
//  /post/{:\\d+}   // 同上，但是没有命名；
//
//
//
// 命名参数
//
// 若路由字符串中，所有的正则表达式都只有名称部分（没有冒号及之后的内容），
// 则会被转换成命名参数，因为不需要作正则验证，性能会比较正则稍微好上一些。
//  /posts/{id}                // 命名参数
//  /blog/{action}/{page:\\d+} // 正则，page 使用了正则匹配
//
//
//
// 通配符
//
// 在路由字符串最后加上 /* 可以启到通配符的作用，但是不可用于中间。
//  /blog/assets/*
//  /blog/{posts}/*
//  /blog/{tags:\\w+}/*
//  /blog/*/assets      // 不正确
//  /blog/assets*       // 不正确
//
//
//
// 路由参数：
//
// 通过正则表达式匹配的路由，其中带命名的参数可通过 GetParams() 获取：
//  params := GetParams(r)
//
//  id, err := params.Int("id")
//  // 或是
//  id := params.MustInt("id", 0) // 0 表示在无法获取 id 参数的默认值
//
//
//
// 路径匹配规则：
//
// 可能会出现多条记录与同一请求都匹配的情况，这种情况下，
// 系统会找到一条认为最匹配的路由来处理，判断规则如下：
//  1. 普通路由优先于正则路由判断；
//  1. 正则路由优先于命名路由；
//  1. 完全匹配的路由项优先于有通配符的路由；
//  1. 带通配符的各类路由，按照 1、2 规则执行。
//
//
//
// OPTIONS:
//
// 默认情况下，用户无须显示地实现它，系统会自动实现。
// 当然用户也可以使用 *.Options() 函数指定特定的数据；
// 或是直接使用 *.Add() 指定一个自定义的实现方式。
//
// 如果不需要的话，也可以在 New() 中将 disableOptions 设置为 true。
// 通过 *.Add 和 *.Remove 来显示的指定或是删除 OPTIONS，不受是否禁用的影响。
//  m := mux.New(...)
//  m.Get("/posts/{id}", nil)     // 默认情况下， OPTIONS 的报头为 GET, OPTIONS
//  m.Options("/posts/{id}", "*") // 强制改成 *
//  m.Delete("/posts/{id}", nil)  // OPTIONS 依然为 *
//
//  m.Remove("/posts/{id}", http.MethodOptions) // 在当前路由上禁用 OPTIONS
//  m.Add("/posts/{id}", h, http.MethodOptions) // 显示指定一个处理函数 h
//
//
//
// 适用范围
//
// 由于路由项采用了切片(slice) 的形式保存路由项，
// 如果在运行过程中需要大量的增删路由操作，性能上会比较差，
// 建议使用其它的库的代替。其它情况下，性能还是不错的，
// 具体的可运行 `go test -bench=.` 查看。
package mux // import "github.com/issue9/mux"
<commit_msg>修正文档错误<commit_after>// Copyright 2014 by caixw, All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.

// Package mux 是一个实现了 http.Handler 的中间件，为用户提供了路由匹配等功能。
//
//  m := mux.New(false, false, nil, nil).
//          Get("/users/1", h).
//          Post("/login", h).
//          Get("/posts/{id:\\d+}", h).  // 正则路由
//          Options("/users/1", "GET")   // 手动指定 OPTIONS 请求的返回内容。
//
//  // 统一前缀路径的路由
//  p := m.Prefix("/api")
//  p.Get("/logout", h) // 相当于 m.Get("/api/logout", h)
//  p.Post("/login", h) // 相当于 m.Get("/api/login", h)
//
//  // 对同一资源的不同操作
//  res := p.Resource("/users/{id\\d+}")
//  res.Get(h)   // 相当于 m.Get("/api/users/{id}", h)
//  res.Post(h)  // 相当于 m.Post("/api/users/{id}", h)
//  res.URL(map[string]string{"id": "5"}, "") // /users/5
//
//  http.ListenAndServe(":8080", m)
//
//
//
// 正则表达式
//
// 路由中支持以正则表达式的方式进行匹配，表达式以大括号包含，内部以冒号分隔，
// 前半部分为变量的名称，后半部分为变量可匹配类型的正则表达式。比如：
//  /post/{id:\\d+} // id 的值只能为 \d+，\d+ 为正则表达式；
//  /post/{:\\d+}   // 同上，但是没有命名；
//
//
//
// 命名参数
//
// 若路由字符串中，所有的正则表达式都只有名称部分（没有冒号及之后的内容），
// 则会被转换成命名参数，因为不需要作正则验证，性能会比较正则稍微好上一些。
//  /posts/{id}                // 命名参数
//  /blog/{action}/{page:\\d+} // 正则，page 使用了正则匹配
//
//
//
// 通配符
//
// 在路由字符串最后加上 /* 可以启到通配符的作用，但是不可用于中间。
//  /blog/assets/*
//  /blog/{posts}/*
//  /blog/{tags:\\w+}/*
//  /blog/*/assets      // 不正确
//  /blog/assets*       // 不正确
//
//
//
// 路由参数：
//
// 通过正则表达式匹配的路由，其中带命名的参数可通过 GetParams() 获取：
//  params := GetParams(r)
//
//  id, err := params.Int("id")
//  // 或是
//  id := params.MustInt("id", 0) // 0 表示在无法获取 id 参数的默认值
//
//
//
// 路径匹配规则：
//
// 可能会出现多条记录与同一请求都匹配的情况，这种情况下，
// 系统会找到一条认为最匹配的路由来处理，判断规则如下：
//  1. 普通路由优先于正则路由判断；
//  1. 正则路由优先于命名路由；
//  1. 完全匹配的路由项优先于有通配符的路由；
//  1. 带通配符的各类路由，按照 1、2 规则执行。
//
//
//
// OPTIONS:
//
// 默认情况下，用户无须显示地实现它，系统会自动实现。
// 当然用户也可以使用 *.Options() 函数指定特定的数据；
// 或是直接使用 *.Add() 指定一个自定义的实现方式。
//
// 如果不需要的话，也可以在 New() 中将 disableOptions 设置为 true。
// 通过 *.Add 和 *.Remove 来显示的指定或是删除 OPTIONS，不受是否禁用的影响。
//  m := mux.New(...)
//  m.Get("/posts/{id}", nil)     // 默认情况下， OPTIONS 的报头为 GET, OPTIONS
//  m.Options("/posts/{id}", "*") // 强制改成 *
//  m.Delete("/posts/{id}", nil)  // OPTIONS 依然为 *
//
//  m.Remove("/posts/{id}", http.MethodOptions) // 在当前路由上禁用 OPTIONS
//  m.Add("/posts/{id}", h, http.MethodOptions) // 显示指定一个处理函数 h
//
//
//
// 适用范围
//
// 由于路由项采用了切片(slice) 的形式保存路由项，
// 如果在运行过程中需要大量的增删路由操作，性能上会比较差，
// 建议使用其它的库的代替。其它情况下，性能还是不错的，
// 具体的可运行 `go test -bench=.` 查看。
package mux // import "github.com/issue9/mux"
<|endoftext|>


<commit_before>/*
Package telnet provides TELNET and TELNETS client and server implementations
in a style similar to the "net/http" library that is part of the Go standard library,
including support for "middleware"; TELNETS is secure TELNET, with the TELNET protocol
over a secured TLS (or SSL) connection.

Example TELNET Server

ListenAndServe starts a (un-secure) TELNET server with a given address and handler.

	handler := telnet.EchoHandler

	err := telnet.ListenAndServe(":23", handler)
	if nil != err {
		panic(err)
	}

Example TELNETS Server

ListenAndServeTLS starts a (secure) TELNETS server with a given address and handler,
using the specified "cert.pem" and "key.pem" files.

	handler := telnet.EchoHandler

	err := telnet.ListenAndServeTLS(":992", "cert.pem", "key.pem", handler)
	if nil != err {
		panic(err)
	}

TELNET vs TELNETS

If you are communicating over the open Internet, you should be using (the secure) TELNETS and ListenAndServeTLS.

If you are communicating just on localhost, then using just (the un-secure) TELNET and telnet.ListenAndServe may be OK.

If you are not sure which to use, use TELNETS and ListenAndServeTLS.

Example TELNET Shell Server

The previous 2 exaple servers were very very simple. Specifically, they just echoed back whatever
you submitted to it.

If you typed:

	Apple Banana Cherry\r\n

... it would send back:

	Apple Banana Cherry\r\n

(Exactly the same data you sent it.)

A more useful TELNET server can be made using the "github.com/reiver/go-telnet/telsh" sub-package.

The `telsh` sub-package provides "middleware" that enables you to create a "shell" interface (also
called a "command line interface" or "CLI") which most people would expect when using TELNET OR TELNETS.

For example:

	package main

	import (
		"github.com/reiver/go-oi"
		"github.com/reiver/go-telnet"
		"github.com/reiver/go-telnet/telsh"

		"time"
	)

	func main() {

		shellHandler := telsh.NewShellHandler()

		commandName := "date"
		shellHandler.Register(commandName, danceProducer)

		commandName = "animate"
		shellHandler.Register(commandName, animateProducer)

		addr := ":23"
		if err := telnet.ListenAndServe(addr, shellHandler); nil != err {
			panic(err)
		}
	}

Note that in the example, so far, we have registered 2 commands: `date` and `animate`.

For this to actually work, we need to have code for the `date` and `animate` commands.

The actual implemenation for the `date` command could be done like the following:

	func dateHandlerFunc(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {
		const layout = "Mon Jan 2 15:04:05 -0700 MST 2006"
		s := time.Now().Format(layout)

		if _, err := oi.LongWriteString(stdout, s); nil != err {
			return err
		}

		return nil
	}

	func dateProducerFunc(ctx telsh.Context, name string, args ...string) telsh.Handler{
		return telsh.PromoteHandlerFunc(dateHandler)
	}

	var dateProducer = ProducerFunc(dateProducerFunc)

Note that your "real" work is in the `dateHandlerFunc` func.

And the actual implementation for the `animate` command could as done as follows:

	func animateHandlerFunc(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {

		for i:=0; i<20; i++ {
			oi.LongWriteString(stdout, "\r⠋")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠙")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠹")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠸")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠼")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠴")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠦")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠧")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠇")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠏")
			time.Sleep(50*time.Millisecond)
		}
		oi.LongWriteString(stdout, "\r \r\n")

		return nil
	}

	func animateProducerFunc(ctx telsh.Context, name string, args ...string) telsh.Handler{
		return telsh.PromoteHandlerFunc(animateHandler)
	}

	var animateProducer = ProducerFunc(animateProducerFunc)

Again, note that your "real" work is in the `animateHandlerFunc` func.

Generating PEM Files

If you are using the telnet.ListenAndServeTLS func or the telnet.Server.ListenAndServeTLS method, you will need to
supply "cert.pem" and "key.pem" files.

If you do not already have these files, the Go soure code contains a tool for generating these files for you.

It can be found at:

	$GOROOT/src/crypto/tls/generate_cert.go

So, for example, if your `$GOROOT` is the "/usr/local/go" directory, then it would be at:

	/usr/local/go/src/crypto/tls/generate_cert.go

If you run the command:

	go run $GOROOT/src/crypto/tls/generate_cert.go --help

... then you get the help information for "generate_cert.go".

Of course, you would replace or set `$GOROOT` with whatever your path actualy is. Again, for example,
if your `$GOROOT` is the "/usr/local/go" directory, then it would be:

	go run /usr/local/go/src/crypto/tls/generate_cert.go --help

To demonstrate the usage of "generate_cert.go", you might run the following to generate certificates
that were bound to the hosts `127.0.0.1` and `localhost`:

	go run /usr/local/go/src/crypto/tls/generate_cert.go --ca --host='127.0.0.1,localhost'

If you are not sure where "generate_cert.go" is on your computer, on Linux and Unix based systems, you might
be able to find the file with the command:

	locate /src/crypto/tls/generate_cert.go

(If it finds it, it should output the full path to this file.)

Terminal Codes

Terminal codes (also sometimes called 'terminal control codes') are used to issue various kinds of commands
to the terminal.

(Note that 'terminal control codes' are a completely separate concept for 'TELNET commands',
and the two should NOT be conflated or confused.)

The most common types of 'terminal codes' are the 'ANSI escape codes'. (Although there are other types too.)

ANSI Escape Codes

ANSI escape codes (also sometimes called 'ANSI escape sequences') are a common type of 'terminal code' used
to do things such as:

• moving the cursor,

• erasing the display,

• erasing the line,

• setting the graphics mode,

• setting the foregroup color,

• setting the background color,

• setting the screen resolution, and

• setting keyboard strings.

Setting The Foreground Color With ANSI Escape Codes

One of the abilities of ANSI escape codes is to set the foreground color.

Here is a table showing codes for this:

	| ANSI Color   | Go string    | Go []byte                       |
	| ------------ | ------------ | ------------------------------- |
	| Black        | `"\x1b[30m"` | `[]byte{27, '[', '3','0', 'm'}` |
	| Red          | `"\x1b[31m"` | `[]byte{27, '[', '3','1', 'm'}` |
	| Green        | `"\x1b[32m"` | `[]byte{27, '[', '3','2', 'm'}` |
	| Brown/Yellow | `"\x1b[33m"` | `[]byte{27, '[', '3','3', 'm'}` |
	| Blue         | `"\x1b[34m"` | `[]byte{27, '[', '3','4', 'm'}` |
	| Magenta      | `"\x1b[35m"` | `[]byte{27, '[', '3','5', 'm'}` |
	| Cyan         | `"\x1b[36m"` | `[]byte{27, '[', '3','6', 'm'}` |
	| Gray/White   | `"\x1b[37m"` | `[]byte{27, '[', '3','7', 'm'}` |

(Note that in the `[]byte` that the first `byte` is the number `27` (which
is the "escape" character) where the third and fouth characters are the
**not** number literals, but instead character literals `'3'` and whatever.)

Setting The Background Color With ANSI Escape Codes

Another of the abilities of ANSI escape codes is to set the background color.

	| ANSI Color   | Go string    | Go []byte                       |
	| ------------ | ------------ | ------------------------------- |
	| Black        | `"\x1b[40m"` | `[]byte{27, '[', '4','0', 'm'}` |
	| Red          | `"\x1b[41m"` | `[]byte{27, '[', '4','1', 'm'}` |
	| Green        | `"\x1b[42m"` | `[]byte{27, '[', '4','2', 'm'}` |
	| Brown/Yellow | `"\x1b[43m"` | `[]byte{27, '[', '4','3', 'm'}` |
	| Blue         | `"\x1b[44m"` | `[]byte{27, '[', '4','4', 'm'}` |
	| Magenta      | `"\x1b[45m"` | `[]byte{27, '[', '4','5', 'm'}` |
	| Cyan         | `"\x1b[46m"` | `[]byte{27, '[', '4','6', 'm'}` |
	| Gray/White   | `"\x1b[47m"` | `[]byte{27, '[', '4','7', 'm'}` |

(Note that in the `[]byte` that the first `byte` is the number `27` (which
is the "escape" character) where the third and fouth characters are the
**not** number literals, but instead character literals `'4'` and whatever.)

Using ANSI Escape Codes

In Go code, if I wanted to use an ANSI escape code to use a blue background,
a white foreground, and bold, I could do that with the ANSI escape code:

	"\x1b[44;37;1m"

Note that that start with byte value 27, which we have encoded as hexadecimal
as \x1b. Followed by the '[' character.

Coming after that is the sub-string "44", which is the code that sets our background color to blue.

We follow that with the ';' character (which separates codes).

And the after that comes the sub-string "37", which is the code that set our foreground color to white.

After that, we follow with another ";" character (which, again, separates codes).

And then we follow it the sub-string "1", which is the code that makes things bold.

And finally, the ANSI escape sequence is finished off with the 'm' character.

To show this in a more complete example, our `dateHandlerFunc` from before could incorporate ANSI escape sequences as follows:

	func dateHandlerFunc(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {
		const layout = "Mon Jan 2 15:04:05 -0700 MST 2006"
		s := "\x1b[44;37;1m" + time.Now().Format(layout) + "\x1b[0m"

		if _, err := oi.LongWriteString(stdout, s); nil != err {
			return err
		}

		return nil
	}

Note that in that example, in addition to using the ANSI escape sequence "\x1b[44;37;1m"
to set the background color to blue, set the foreground color to white, and make it bold,
we also used the ANSI escape sequence "\x1b[0m" to reset the background and foreground colors
and boldness back to "normal".

*/
package telnet
<commit_msg>updated docs<commit_after>/*
Package telnet provides TELNET and TELNETS client and server implementations
in a style similar to the "net/http" library that is part of the Go standard library,
including support for "middleware"; TELNETS is secure TELNET, with the TELNET protocol
over a secured TLS (or SSL) connection.

Example TELNET Server

ListenAndServe starts a (un-secure) TELNET server with a given address and handler.

	handler := telnet.EchoHandler

	err := telnet.ListenAndServe(":23", handler)
	if nil != err {
		panic(err)
	}

Example TELNETS Server

ListenAndServeTLS starts a (secure) TELNETS server with a given address and handler,
using the specified "cert.pem" and "key.pem" files.

	handler := telnet.EchoHandler

	err := telnet.ListenAndServeTLS(":992", "cert.pem", "key.pem", handler)
	if nil != err {
		panic(err)
	}

TELNET vs TELNETS

If you are communicating over the open Internet, you should be using (the secure) TELNETS and ListenAndServeTLS.

If you are communicating just on localhost, then using just (the un-secure) TELNET and telnet.ListenAndServe may be OK.

If you are not sure which to use, use TELNETS and ListenAndServeTLS.

Example TELNET Shell Server

The previous 2 exaple servers were very very simple. Specifically, they just echoed back whatever
you submitted to it.

If you typed:

	Apple Banana Cherry\r\n

... it would send back:

	Apple Banana Cherry\r\n

(Exactly the same data you sent it.)

A more useful TELNET server can be made using the "github.com/reiver/go-telnet/telsh" sub-package.

The `telsh` sub-package provides "middleware" that enables you to create a "shell" interface (also
called a "command line interface" or "CLI") which most people would expect when using TELNET OR TELNETS.

For example:

	package main

	import (
		"github.com/reiver/go-oi"
		"github.com/reiver/go-telnet"
		"github.com/reiver/go-telnet/telsh"

		"time"
	)

	func main() {

		shellHandler := telsh.NewShellHandler()

		commandName := "date"
		shellHandler.Register(commandName, danceProducer)

		commandName = "animate"
		shellHandler.Register(commandName, animateProducer)

		addr := ":23"
		if err := telnet.ListenAndServe(addr, shellHandler); nil != err {
			panic(err)
		}
	}

Note that in the example, so far, we have registered 2 commands: `date` and `animate`.

For this to actually work, we need to have code for the `date` and `animate` commands.

The actual implemenation for the `date` command could be done like the following:

	func dateHandlerFunc(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {
		const layout = "Mon Jan 2 15:04:05 -0700 MST 2006"
		s := time.Now().Format(layout)

		if _, err := oi.LongWriteString(stdout, s); nil != err {
			return err
		}

		return nil
	}

	func dateProducerFunc(ctx telsh.Context, name string, args ...string) telsh.Handler{
		return telsh.PromoteHandlerFunc(dateHandler)
	}

	var dateProducer = ProducerFunc(dateProducerFunc)

Note that your "real" work is in the `dateHandlerFunc` func.

And the actual implementation for the `animate` command could be done as follows:

	func animateHandlerFunc(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {

		for i:=0; i<20; i++ {
			oi.LongWriteString(stdout, "\r⠋")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠙")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠹")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠸")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠼")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠴")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠦")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠧")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠇")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠏")
			time.Sleep(50*time.Millisecond)
		}
		oi.LongWriteString(stdout, "\r \r\n")

		return nil
	}

	func animateProducerFunc(ctx telsh.Context, name string, args ...string) telsh.Handler{
		return telsh.PromoteHandlerFunc(animateHandler)
	}

	var animateProducer = ProducerFunc(animateProducerFunc)

Again, note that your "real" work is in the `animateHandlerFunc` func.

Generating PEM Files

If you are using the telnet.ListenAndServeTLS func or the telnet.Server.ListenAndServeTLS method, you will need to
supply "cert.pem" and "key.pem" files.

If you do not already have these files, the Go soure code contains a tool for generating these files for you.

It can be found at:

	$GOROOT/src/crypto/tls/generate_cert.go

So, for example, if your `$GOROOT` is the "/usr/local/go" directory, then it would be at:

	/usr/local/go/src/crypto/tls/generate_cert.go

If you run the command:

	go run $GOROOT/src/crypto/tls/generate_cert.go --help

... then you get the help information for "generate_cert.go".

Of course, you would replace or set `$GOROOT` with whatever your path actualy is. Again, for example,
if your `$GOROOT` is the "/usr/local/go" directory, then it would be:

	go run /usr/local/go/src/crypto/tls/generate_cert.go --help

To demonstrate the usage of "generate_cert.go", you might run the following to generate certificates
that were bound to the hosts `127.0.0.1` and `localhost`:

	go run /usr/local/go/src/crypto/tls/generate_cert.go --ca --host='127.0.0.1,localhost'

If you are not sure where "generate_cert.go" is on your computer, on Linux and Unix based systems, you might
be able to find the file with the command:

	locate /src/crypto/tls/generate_cert.go

(If it finds it, it should output the full path to this file.)

Terminal Codes

Terminal codes (also sometimes called 'terminal control codes') are used to issue various kinds of commands
to the terminal.

(Note that 'terminal control codes' are a completely separate concept for 'TELNET commands',
and the two should NOT be conflated or confused.)

The most common types of 'terminal codes' are the 'ANSI escape codes'. (Although there are other types too.)

ANSI Escape Codes

ANSI escape codes (also sometimes called 'ANSI escape sequences') are a common type of 'terminal code' used
to do things such as:

• moving the cursor,

• erasing the display,

• erasing the line,

• setting the graphics mode,

• setting the foregroup color,

• setting the background color,

• setting the screen resolution, and

• setting keyboard strings.

Setting The Foreground Color With ANSI Escape Codes

One of the abilities of ANSI escape codes is to set the foreground color.

Here is a table showing codes for this:

	| ANSI Color   | Go string    | Go []byte                       |
	| ------------ | ------------ | ------------------------------- |
	| Black        | `"\x1b[30m"` | `[]byte{27, '[', '3','0', 'm'}` |
	| Red          | `"\x1b[31m"` | `[]byte{27, '[', '3','1', 'm'}` |
	| Green        | `"\x1b[32m"` | `[]byte{27, '[', '3','2', 'm'}` |
	| Brown/Yellow | `"\x1b[33m"` | `[]byte{27, '[', '3','3', 'm'}` |
	| Blue         | `"\x1b[34m"` | `[]byte{27, '[', '3','4', 'm'}` |
	| Magenta      | `"\x1b[35m"` | `[]byte{27, '[', '3','5', 'm'}` |
	| Cyan         | `"\x1b[36m"` | `[]byte{27, '[', '3','6', 'm'}` |
	| Gray/White   | `"\x1b[37m"` | `[]byte{27, '[', '3','7', 'm'}` |

(Note that in the `[]byte` that the first `byte` is the number `27` (which
is the "escape" character) where the third and fouth characters are the
**not** number literals, but instead character literals `'3'` and whatever.)

Setting The Background Color With ANSI Escape Codes

Another of the abilities of ANSI escape codes is to set the background color.

	| ANSI Color   | Go string    | Go []byte                       |
	| ------------ | ------------ | ------------------------------- |
	| Black        | `"\x1b[40m"` | `[]byte{27, '[', '4','0', 'm'}` |
	| Red          | `"\x1b[41m"` | `[]byte{27, '[', '4','1', 'm'}` |
	| Green        | `"\x1b[42m"` | `[]byte{27, '[', '4','2', 'm'}` |
	| Brown/Yellow | `"\x1b[43m"` | `[]byte{27, '[', '4','3', 'm'}` |
	| Blue         | `"\x1b[44m"` | `[]byte{27, '[', '4','4', 'm'}` |
	| Magenta      | `"\x1b[45m"` | `[]byte{27, '[', '4','5', 'm'}` |
	| Cyan         | `"\x1b[46m"` | `[]byte{27, '[', '4','6', 'm'}` |
	| Gray/White   | `"\x1b[47m"` | `[]byte{27, '[', '4','7', 'm'}` |

(Note that in the `[]byte` that the first `byte` is the number `27` (which
is the "escape" character) where the third and fouth characters are the
**not** number literals, but instead character literals `'4'` and whatever.)

Using ANSI Escape Codes

In Go code, if I wanted to use an ANSI escape code to use a blue background,
a white foreground, and bold, I could do that with the ANSI escape code:

	"\x1b[44;37;1m"

Note that that start with byte value 27, which we have encoded as hexadecimal
as \x1b. Followed by the '[' character.

Coming after that is the sub-string "44", which is the code that sets our background color to blue.

We follow that with the ';' character (which separates codes).

And the after that comes the sub-string "37", which is the code that set our foreground color to white.

After that, we follow with another ";" character (which, again, separates codes).

And then we follow it the sub-string "1", which is the code that makes things bold.

And finally, the ANSI escape sequence is finished off with the 'm' character.

To show this in a more complete example, our `dateHandlerFunc` from before could incorporate ANSI escape sequences as follows:

	func dateHandlerFunc(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {
		const layout = "Mon Jan 2 15:04:05 -0700 MST 2006"
		s := "\x1b[44;37;1m" + time.Now().Format(layout) + "\x1b[0m"

		if _, err := oi.LongWriteString(stdout, s); nil != err {
			return err
		}

		return nil
	}

Note that in that example, in addition to using the ANSI escape sequence "\x1b[44;37;1m"
to set the background color to blue, set the foreground color to white, and make it bold,
we also used the ANSI escape sequence "\x1b[0m" to reset the background and foreground colors
and boldness back to "normal".

*/
package telnet
<|endoftext|>


<commit_before>// package goenc contains functions for working with encryption
// work is derived from many sources:
//
// http://stackoverflow.com/questions/21151714/go-generate-an-ssh-public-key
// https://github.com/andmarios/golang-nacl-secretbox
// https://golang.org/pkg/crypto/cipher/

package goenc

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"io"

	"bytes"

	"io/ioutil"

	"fmt"

	"golang.org/x/crypto/nacl/secretbox"
	"golang.org/x/crypto/ssh"
)

/*
	TODO(cmc) - Add encrypted private key decryption
	TODO(cmc) - Support loading and parsing private/public keys from different formats
	TODO(cmc) - Finish writing tests
	TODO(cmc) - Add HMAC support
	TODO(cmc) - Verify this isn't horrifically insecure

*/

const (
	keySize = 32
)

// Decrypt decrypts ciphertext using the given key
func Decrypt(ciphertext, key []byte) ([]byte, error) {

	// Create the AES cipher
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	if len(ciphertext) < aes.BlockSize {
		return nil, errors.New("Ciphertext is shorter than aes.BlockSize")
	}

	// get first 16 bytes from ciphertext
	iv := ciphertext[:aes.BlockSize]

	// Remove the IV from the ciphertext
	ciphertext = ciphertext[aes.BlockSize:]

	// Return a decrypted stream
	stream := cipher.NewCFBDecrypter(block, iv)

	// Decrypt bytes from ciphertext
	stream.XORKeyStream(ciphertext, ciphertext)

	return ciphertext, nil
}

// Encrypt encrypts ciphertext using the given key.
// NOTE: This is not secure without being authenticated (crypto/hmac)
func Encrypt(plaintext, key []byte) ([]byte, error) {
	// Create the AES cipher
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	// Empty array of 16 + plaintext length
	// Include the IV at the beginning
	ciphertext := make([]byte, aes.BlockSize+len(plaintext))

	// Slice of first 16 bytes
	iv := ciphertext[:aes.BlockSize]

	// Write 16 rand bytes to fill iv
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		return nil, err
	}

	// Return an encrypted stream
	stream := cipher.NewCFBEncrypter(block, iv)

	// Encrypt bytes from plaintext to ciphertext
	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
	return ciphertext, nil
}

// DecryptString decrypts ciphertext using the given key
func DecryptString(ciphertext, key string) (string, error) {
	b, err := Decrypt([]byte(ciphertext), []byte(key))
	return string(b), err
}

// EncryptString encrypts ciphertext using the given key
func EncryptString(plaintext, key string) (string, error) {
	b, err := Encrypt([]byte(plaintext), []byte(key))
	return string(b), err
}

// SSHKeyPair generates private and public key bytes
func SSHKeyPair() (privateKeyBytes, publicKeyBytes []byte, err error) {
	privateKey, err := rsa.GenerateKey(rand.Reader, 1024)
	if err != nil {
		return nil, nil, err
	}
	buf := bytes.NewBuffer(privateKeyBytes)
	privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}
	if err = pem.Encode(buf, privateKeyPEM); err != nil {
		return nil, nil, err
	}

	// generate and write public key
	pub, err := ssh.NewPublicKey(&privateKey.PublicKey)
	if err != nil {
		return nil, nil, err
	}
	publicKeyBytes = ssh.MarshalAuthorizedKey(pub)
	return
}

// GenerateAndSaveSSHKeyPair generates a new ssh private key and public key and saves them to the given paths
func GenerateAndSaveSSHKeyPair(privateKeyPath, pubkeyPath string) error {
	pr, pub, err := SSHKeyPair()
	if err != nil {
		return err
	}
	if err := ioutil.WriteFile(privateKeyPath, pr, 0600); err != nil {
		return err
	}
	return ioutil.WriteFile(pubkeyPath, pub, 0644)
}

const (
	nonceSize = 24
)

// NaCLEncrypt salts a key using pad and encrypts a message
func NaCLEncrypt(pad, key, message []byte) (out []byte, err error) {
	if len(pad) == 0 {
		return nil, errors.New("pad had a length of 0, it must be at least 32 bytes")
	}
	// NaCl's key has a constant size of 32 bytes.
	// The user provided key probably is less than that. We pad it with
	// a long enough string and truncate anything we don't need later on.
	key = append(key, pad...)

	// NaCl's key should be of type [32]byte.
	// Here we create it and truncate key bytes beyond 32
	naclKey := new([keySize]byte)
	copy(naclKey[:], key[:keySize])

	// Nonce is a [24]byte variable that should be unique amongst messages.
	// Nonce is generated by the encrypter.
	// 24 bytes is large enough to avoid collisions while reading from rand.
	// If it suits you better, you may use a non random nonce (e.g a counter).
	// It only has to change per message.
	nonce := new([nonceSize]byte)
	// Read bytes from random and put them in nonce until it is full.
	_, err = io.ReadFull(rand.Reader, nonce[:])
	if err != nil {
		return nil, fmt.Errorf("Could not read from random: %s", err)
	}
	// out will hold the nonce and the encrypted message (ciphertext)
	out = make([]byte, nonceSize)
	// Copy the nonce to the start of out
	copy(out, nonce[:])
	// Encrypt the message and append it to out, assign the result to out
	out = secretbox.Seal(out, message, nonce, naclKey)
	return out, err
}

// NaCLDecrypt salts a key using pad and decrypts a message
func NaCLDecrypt(pad, key, data []byte) (out []byte, err error) {
	key = append(key, pad...)

	// NaCl's key should be of type [32]byte.
	// Here we create it and truncate key bytes beyond 32
	naclKey := new([keySize]byte)
	copy(naclKey[:], key[:keySize])

	// The nonce is of type [24]byte and part of the data we will receive
	nonce := new([nonceSize]byte)

	// Read the nonce from in, it is in the first 24 bytes
	copy(nonce[:], data[:nonceSize])

	// Decrypt the output of secretbox.Seal which contains the nonce and
	// the encrypted message
	message, ok := secretbox.Open(nil, data[nonceSize:], nonce, naclKey)
	if ok {
		return message, nil
	}
	return nil, errors.New("Decryption failed")
}

// RandomPadNaCLEncrypt generates a random pad and returns the encrypted data, the pad, and an error if any
func RandomPadNaCLEncrypt(key, message []byte) (pad, out []byte, err error) {
	pad = make([]byte, 32)
	_, err = rand.Read(pad)
	if err != nil {
		return
	}
	out, err = NaCLEncrypt(pad, key, message)
	return
}
<commit_msg>make todos uniform<commit_after>// package goenc contains functions for working with encryption
// work is derived from many sources:
//
// http://stackoverflow.com/questions/21151714/go-generate-an-ssh-public-key
// https://github.com/andmarios/golang-nacl-secretbox
// https://golang.org/pkg/crypto/cipher/

package goenc

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"io"

	"bytes"

	"io/ioutil"

	"fmt"

	"golang.org/x/crypto/nacl/secretbox"
	"golang.org/x/crypto/ssh"
)

/*
	TODO(cmc): Add encrypted private key decryption
	TODO(cmc): Support loading and parsing private/public keys from different formats
	TODO(cmc): Finish writing tests
	TODO(cmc): Add HMAC support
	TODO(cmc): Verify this isn't horrifically insecure

*/

const (
	keySize = 32
)

// Decrypt decrypts ciphertext using the given key
func Decrypt(ciphertext, key []byte) ([]byte, error) {

	// Create the AES cipher
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	if len(ciphertext) < aes.BlockSize {
		return nil, errors.New("Ciphertext is shorter than aes.BlockSize")
	}

	// get first 16 bytes from ciphertext
	iv := ciphertext[:aes.BlockSize]

	// Remove the IV from the ciphertext
	ciphertext = ciphertext[aes.BlockSize:]

	// Return a decrypted stream
	stream := cipher.NewCFBDecrypter(block, iv)

	// Decrypt bytes from ciphertext
	stream.XORKeyStream(ciphertext, ciphertext)

	return ciphertext, nil
}

// Encrypt encrypts ciphertext using the given key.
// NOTE: This is not secure without being authenticated (crypto/hmac)
func Encrypt(plaintext, key []byte) ([]byte, error) {
	// Create the AES cipher
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	// Empty array of 16 + plaintext length
	// Include the IV at the beginning
	ciphertext := make([]byte, aes.BlockSize+len(plaintext))

	// Slice of first 16 bytes
	iv := ciphertext[:aes.BlockSize]

	// Write 16 rand bytes to fill iv
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		return nil, err
	}

	// Return an encrypted stream
	stream := cipher.NewCFBEncrypter(block, iv)

	// Encrypt bytes from plaintext to ciphertext
	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)
	return ciphertext, nil
}

// DecryptString decrypts ciphertext using the given key
func DecryptString(ciphertext, key string) (string, error) {
	b, err := Decrypt([]byte(ciphertext), []byte(key))
	return string(b), err
}

// EncryptString encrypts ciphertext using the given key
func EncryptString(plaintext, key string) (string, error) {
	b, err := Encrypt([]byte(plaintext), []byte(key))
	return string(b), err
}

// SSHKeyPair generates private and public key bytes
func SSHKeyPair() (privateKeyBytes, publicKeyBytes []byte, err error) {
	privateKey, err := rsa.GenerateKey(rand.Reader, 1024)
	if err != nil {
		return nil, nil, err
	}
	buf := bytes.NewBuffer(privateKeyBytes)
	privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}
	if err = pem.Encode(buf, privateKeyPEM); err != nil {
		return nil, nil, err
	}

	// generate and write public key
	pub, err := ssh.NewPublicKey(&privateKey.PublicKey)
	if err != nil {
		return nil, nil, err
	}
	publicKeyBytes = ssh.MarshalAuthorizedKey(pub)
	return
}

// GenerateAndSaveSSHKeyPair generates a new ssh private key and public key and saves them to the given paths
func GenerateAndSaveSSHKeyPair(privateKeyPath, pubkeyPath string) error {
	pr, pub, err := SSHKeyPair()
	if err != nil {
		return err
	}
	if err := ioutil.WriteFile(privateKeyPath, pr, 0600); err != nil {
		return err
	}
	return ioutil.WriteFile(pubkeyPath, pub, 0644)
}

const (
	nonceSize = 24
)

// NaCLEncrypt salts a key using pad and encrypts a message
func NaCLEncrypt(pad, key, message []byte) (out []byte, err error) {
	if len(pad) == 0 {
		return nil, errors.New("pad had a length of 0, it must be at least 32 bytes")
	}
	// NaCl's key has a constant size of 32 bytes.
	// The user provided key probably is less than that. We pad it with
	// a long enough string and truncate anything we don't need later on.
	key = append(key, pad...)

	// NaCl's key should be of type [32]byte.
	// Here we create it and truncate key bytes beyond 32
	naclKey := new([keySize]byte)
	copy(naclKey[:], key[:keySize])

	// Nonce is a [24]byte variable that should be unique amongst messages.
	// Nonce is generated by the encrypter.
	// 24 bytes is large enough to avoid collisions while reading from rand.
	// If it suits you better, you may use a non random nonce (e.g a counter).
	// It only has to change per message.
	nonce := new([nonceSize]byte)
	// Read bytes from random and put them in nonce until it is full.
	_, err = io.ReadFull(rand.Reader, nonce[:])
	if err != nil {
		return nil, fmt.Errorf("Could not read from random: %s", err)
	}
	// out will hold the nonce and the encrypted message (ciphertext)
	out = make([]byte, nonceSize)
	// Copy the nonce to the start of out
	copy(out, nonce[:])
	// Encrypt the message and append it to out, assign the result to out
	out = secretbox.Seal(out, message, nonce, naclKey)
	return out, err
}

// NaCLDecrypt salts a key using pad and decrypts a message
func NaCLDecrypt(pad, key, data []byte) (out []byte, err error) {
	key = append(key, pad...)

	// NaCl's key should be of type [32]byte.
	// Here we create it and truncate key bytes beyond 32
	naclKey := new([keySize]byte)
	copy(naclKey[:], key[:keySize])

	// The nonce is of type [24]byte and part of the data we will receive
	nonce := new([nonceSize]byte)

	// Read the nonce from in, it is in the first 24 bytes
	copy(nonce[:], data[:nonceSize])

	// Decrypt the output of secretbox.Seal which contains the nonce and
	// the encrypted message
	message, ok := secretbox.Open(nil, data[nonceSize:], nonce, naclKey)
	if ok {
		return message, nil
	}
	return nil, errors.New("Decryption failed")
}

// RandomPadNaCLEncrypt generates a random pad and returns the encrypted data, the pad, and an error if any
func RandomPadNaCLEncrypt(key, message []byte) (pad, out []byte, err error) {
	pad = make([]byte, 32)
	_, err = rand.Read(pad)
	if err != nil {
		return
	}
	out, err = NaCLEncrypt(pad, key, message)
	return
}
<|endoftext|>


<commit_before>package cmd

import (
	"context"
	"sync"

	"github.com/cybozu-go/log"
)

// Environment implements context-based goroutine management.
type Environment struct {
	ctx       context.Context
	cancel    context.CancelFunc
	wg        sync.WaitGroup
	generator *IDGenerator

	mu       sync.RWMutex
	stopped  bool
	stopCh   chan struct{}
	canceled bool
	err      error
}

// NewEnvironment creates a new Environment.
//
// This function installs a signal handler that calls Cancel when
// SIGINT or SIGTERM is sent.
func NewEnvironment(ctx context.Context) *Environment {
	ctx, cancel := context.WithCancel(ctx)
	e := &Environment{
		ctx:       ctx,
		cancel:    cancel,
		generator: NewIDGenerator(),
		stopCh:    make(chan struct{}),
	}
	return e
}

// Stop just declares no further Go will be called.
//
// Calling Stop is optional if and only if Cancel is guaranteed
// to be called at some point.  For instance, if the program runs
// until SIGINT or SIGTERM, Stop is optional.
func (e *Environment) Stop() {
	e.mu.Lock()

	if !e.stopped {
		e.stopped = true
		close(e.stopCh)
	}

	e.mu.Unlock()
}

// Cancel cancels the base context.
//
// Passed err will be returned by Wait().
// Once canceled, Go() will not start new goroutines.
//
// Note that calling Cancel(nil) is perfectly valid.
// Unlike Stop(), Cancel(nil) cancels the base context and can
// gracefully stop goroutines started by Server.Serve or
// HTTPServer.ListenAndServe.
//
// This returns true if the caller is the first that calls Cancel.
// For second and later calls, Cancel does nothing and returns false.
func (e *Environment) Cancel(err error) bool {
	e.mu.Lock()
	defer e.mu.Unlock()

	if e.canceled {
		return false
	}
	e.canceled = true
	e.err = err
	e.cancel()

	if e.stopped {
		return true
	}

	e.stopped = true
	close(e.stopCh)
	return true
}

// Wait waits for Stop or Cancel, and for all goroutines started by
// Go to finish.
//
// The returned err is the one passed to Cancel, or nil.
// err can be tested by IsSignaled to determine whether the
// program got SIGINT or SIGTERM.
func (e *Environment) Wait() error {
	<-e.stopCh
	log.Info("cmd: waiting for all goroutines to complete", nil)
	e.wg.Wait()
	e.cancel() // in case no one calls Cancel

	e.mu.Lock()
	defer e.mu.Unlock()

	return e.err
}

// Go starts a goroutine that executes f.
//
// f takes a drived context from the base context.  The context
// will be canceled when f returns.
//
// Goroutines started by this function will be waited for by
// Wait until all such goroutines return.
//
// If f returns non-nil error, Cancel is called immediately
// with that error.
//
// f should watch ctx.Done() channel and return quickly when the
// channel is closed.
func (e *Environment) Go(f func(ctx context.Context) error) {
	e.mu.RLock()
	if e.stopped {
		e.mu.RUnlock()
		return
	}
	e.wg.Add(1)
	e.mu.RUnlock()

	go func() {
		ctx, cancel := context.WithCancel(e.ctx)
		defer cancel()
		ctx = WithRequestID(ctx, e.generator.Generate())
		err := f(ctx)
		if err != nil {
			e.Cancel(err)
		}
		e.wg.Done()
	}()
}
<commit_msg>Lower log in Environment.Wait to debug.<commit_after>package cmd

import (
	"context"
	"sync"

	"github.com/cybozu-go/log"
)

// Environment implements context-based goroutine management.
type Environment struct {
	ctx       context.Context
	cancel    context.CancelFunc
	wg        sync.WaitGroup
	generator *IDGenerator

	mu       sync.RWMutex
	stopped  bool
	stopCh   chan struct{}
	canceled bool
	err      error
}

// NewEnvironment creates a new Environment.
//
// This function installs a signal handler that calls Cancel when
// SIGINT or SIGTERM is sent.
func NewEnvironment(ctx context.Context) *Environment {
	ctx, cancel := context.WithCancel(ctx)
	e := &Environment{
		ctx:       ctx,
		cancel:    cancel,
		generator: NewIDGenerator(),
		stopCh:    make(chan struct{}),
	}
	return e
}

// Stop just declares no further Go will be called.
//
// Calling Stop is optional if and only if Cancel is guaranteed
// to be called at some point.  For instance, if the program runs
// until SIGINT or SIGTERM, Stop is optional.
func (e *Environment) Stop() {
	e.mu.Lock()

	if !e.stopped {
		e.stopped = true
		close(e.stopCh)
	}

	e.mu.Unlock()
}

// Cancel cancels the base context.
//
// Passed err will be returned by Wait().
// Once canceled, Go() will not start new goroutines.
//
// Note that calling Cancel(nil) is perfectly valid.
// Unlike Stop(), Cancel(nil) cancels the base context and can
// gracefully stop goroutines started by Server.Serve or
// HTTPServer.ListenAndServe.
//
// This returns true if the caller is the first that calls Cancel.
// For second and later calls, Cancel does nothing and returns false.
func (e *Environment) Cancel(err error) bool {
	e.mu.Lock()
	defer e.mu.Unlock()

	if e.canceled {
		return false
	}
	e.canceled = true
	e.err = err
	e.cancel()

	if e.stopped {
		return true
	}

	e.stopped = true
	close(e.stopCh)
	return true
}

// Wait waits for Stop or Cancel, and for all goroutines started by
// Go to finish.
//
// The returned err is the one passed to Cancel, or nil.
// err can be tested by IsSignaled to determine whether the
// program got SIGINT or SIGTERM.
func (e *Environment) Wait() error {
	<-e.stopCh
	if log.Enabled(log.LvDebug) {
		log.Debug("cmd: waiting for all goroutines to complete", nil)
	}
	e.wg.Wait()
	e.cancel() // in case no one calls Cancel

	e.mu.Lock()
	defer e.mu.Unlock()

	return e.err
}

// Go starts a goroutine that executes f.
//
// f takes a drived context from the base context.  The context
// will be canceled when f returns.
//
// Goroutines started by this function will be waited for by
// Wait until all such goroutines return.
//
// If f returns non-nil error, Cancel is called immediately
// with that error.
//
// f should watch ctx.Done() channel and return quickly when the
// channel is closed.
func (e *Environment) Go(f func(ctx context.Context) error) {
	e.mu.RLock()
	if e.stopped {
		e.mu.RUnlock()
		return
	}
	e.wg.Add(1)
	e.mu.RUnlock()

	go func() {
		ctx, cancel := context.WithCancel(e.ctx)
		defer cancel()
		ctx = WithRequestID(ctx, e.generator.Generate())
		err := f(ctx)
		if err != nil {
			e.Cancel(err)
		}
		e.wg.Done()
	}()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"

	"github.com/progrium/envconfig"
	"github.com/progrium/hostctl/providers"
	"github.com/spf13/cobra"
)

var (
	exportMode  bool
	secretsMode bool
)

func init() {
	envCmd.Flags().BoolVarP(&exportMode, "export", "e", false, "export vars for sourcing later")
	envCmd.Flags().BoolVarP(&secretsMode, "secrets", "s", false, "show secrets or include in export")
	HostctlCmd.AddCommand(envCmd)
}

var envCmd = &cobra.Command{
	Use:   "env",
	Short: "Shows current relevant environment",
	Run: func(cmd *cobra.Command, args []string) {
		for _, v := range envconfig.Vars() {
			printVar(v)
		}
		provider, _ := providers.Get(providerName, false)
		if provider != nil {
			for _, v := range provider.Env().Vars() {
				printVar(v)
			}
		}
	},
}

func printVar(out io.Writer, v *envconfig.ConfigVar) {
	value := v.Value.String()
	if v.Secret {
		if secretsMode {
			value = v.Value.Get().(string)
		} else {
			if exportMode {
				return
			}
		}
	}
	if exportMode {
		fmt.Fprintf(out, "export %s=\"%s\"\n", v.Name, value)
	} else {
		kv := fmt.Sprintf("%s=\"%s\"", v.Name, value)
		fmt.Fprintf(out, "%-40s # %s\n", kv, v.Description)
	}
}
<commit_msg>using PrintEnv<commit_after>package main

import (
	"os"

	"github.com/progrium/envconfig"
	"github.com/progrium/hostctl/providers"
	"github.com/spf13/cobra"
)

var (
	exportMode  bool
	secretsMode bool
)

func init() {
	envCmd.Flags().BoolVarP(&exportMode, "export", "e", false, "export vars for sourcing later")
	envCmd.Flags().BoolVarP(&secretsMode, "secrets", "s", false, "show secrets or include in export")
	HostctlCmd.AddCommand(envCmd)
}

var envCmd = &cobra.Command{
	Use:   "env",
	Short: "Shows current relevant environment",
	Run: func(cmd *cobra.Command, args []string) {
		envconfig.PrintEnv(os.Stdout, exportMode, secretsMode)
		provider, _ := providers.Get(providerName, false)
		if provider != nil {
			provider.Env().PrintEnv(os.Stdout, exportMode, secretsMode)
		}
	},
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"os/exec"
	"syscall"
)

type Process struct {
	Command     string
	Env         Env
	Interactive bool

	*exec.Cmd
}

func NewProcess(workdir, command string, env Env, interactive bool) (p *Process) {
	argv := ShellInvocationCommand(interactive, workdir, command)
	return &Process{
		command, env, interactive, exec.Command(argv[0], argv[1:]...),
	}
}

func (p *Process) Start() error {
	p.Cmd.Env = p.Env.asArray()
	p.PlatformSpecificInit()
	return p.Cmd.Start()
}

func (p *Process) Signal(signal syscall.Signal) {
	group, _ := os.FindProcess(-1 * p.Pid())
	group.Signal(signal)
}

func (p *Process) Pid() int {
	return p.Process.Pid
}
<commit_msg>Eliminate Pid() function<commit_after>package main

import (
	"os"
	"os/exec"
	"syscall"
)

type Process struct {
	Command     string
	Env         Env
	Interactive bool

	*exec.Cmd
}

func NewProcess(workdir, command string, env Env, interactive bool) (p *Process) {
	argv := ShellInvocationCommand(interactive, workdir, command)
	return &Process{
		command, env, interactive, exec.Command(argv[0], argv[1:]...),
	}
}

func (p *Process) Start() error {
	p.Cmd.Env = p.Env.asArray()
	p.PlatformSpecificInit()
	return p.Cmd.Start()
}

func (p *Process) Signal(signal syscall.Signal) {
	group, _ := os.FindProcess(-1 * p.Process.Pid)
	group.Signal(signal)
}
<|endoftext|>


<commit_before>// Package profile provides a simple way to manage runtime/pprof
// profiling of your Go application.
package profile

import (
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"runtime"
	"runtime/pprof"
)

type config struct {
	// Quiet suppresses informational messages during profiling.
	Quiet bool

	// CPUProfile controls if cpu profiling will be enabled.
	CPUProfile bool

	// MemProfile controls if memory profiling will be enabled.
	MemProfile bool

	// BlockProfile controls if block (contention) profiling will
	// be enabled.
	// It defaults to false.
	BlockProfile bool

	// ProfilePath controls the base path where various profiling
	// files are written. If blank, the base path will be generated
	// by ioutil.TempDir.
	ProfilePath string

	// NoShutdownHook controls whether the profiling package should
	// hook SIGINT to write profiles cleanly.
	NoShutdownHook bool
}

// NoShutdownHook controls whether the profiling package should
// hook SIGINT to write profiles cleanly.
// Programs with more sophisticated signal handling should set
// this to true and ensure the Stop() function returned from Start()
// is called during shutdown.
func NoShutdownHook(c *config) { c.NoShutdownHook = true }

// Quiet suppresses informational messages during profiling.
func Quiet(c *config) { c.Quiet = true }

const memProfileRate = 4096

func (c *config) NoProfiles() {
	c.CPUProfile = false
	c.MemProfile = false
	c.BlockProfile = false
}

// CPUProfile controls if cpu profiling will be enabled. It disables an previous profiling settings.
func CPUProfile(c *config) {
	c.NoProfiles()
	c.CPUProfile = true
}

// MemProfile controls if memory profiling will be enabled. It disables any previous profiling settings.
func MemProfile(c *config) {
	c.NoProfiles()
	c.MemProfile = true
}

// BlockProfile controls if block (contention) profiling will be enabled. It disables any previous profiling settings.
func BlockProfile(c *config) {
	c.NoProfiles()
	c.BlockProfile = true
}

// ProfilePath controls the base path where various profiling
// files are written. If blank, the base path will be generated
// by ioutil.TempDir.
func ProfilePath(path string) func(*config) {
	return func(c *config) {
		c.ProfilePath = path
	}
}

type profile struct {
	path string
	*config
	closers []func()
}

func (p *profile) Stop() {
	for _, c := range p.closers {
		c()
	}
}

func defaultOptions() []func(*config) {
	return []func(*config){
		CPUProfile,
		ProfilePath(""),
	}
}

// Start starts a new profiling session.
// The caller should call the Stop method on the value returned
// to cleanly stop profiling.
func Start(options ...func(*config)) interface {
	Stop()
} {
	options = append(defaultOptions(), options...)
	var cfg config
	for _, option := range options {
		option(&cfg)
	}

	path := cfg.ProfilePath
	var err error
	if path == "" {
		path, err = ioutil.TempDir("", "profile")
	} else {
		err = os.MkdirAll(path, 0777)
	}
	if err != nil {
		log.Fatalf("profile: could not create initial output directory: %v", err)
	}
	prof := &profile{
		path:   path,
		config: &cfg,
	}

	if prof.CPUProfile {
		fn := filepath.Join(prof.path, "cpu.pprof")
		f, err := os.Create(fn)
		if err != nil {
			log.Fatalf("profile: could not create cpu profile %q: %v", fn, err)
		}
		if !prof.Quiet {
			log.Printf("profile: cpu profiling enabled, %s", fn)
		}
		pprof.StartCPUProfile(f)
		prof.closers = append(prof.closers, func() {
			pprof.StopCPUProfile()
			f.Close()
		})
	}

	if prof.MemProfile {
		fn := filepath.Join(prof.path, "mem.pprof")
		f, err := os.Create(fn)
		if err != nil {
			log.Fatalf("profile: could not create memory profile %q: %v", fn, err)
		}
		old := runtime.MemProfileRate
		runtime.MemProfileRate = memProfileRate
		if !prof.Quiet {
			log.Printf("profile: memory profiling enabled, %s", fn)
		}
		prof.closers = append(prof.closers, func() {
			pprof.Lookup("heap").WriteTo(f, 0)
			f.Close()
			runtime.MemProfileRate = old
		})
	}

	if prof.BlockProfile {
		fn := filepath.Join(prof.path, "block.pprof")
		f, err := os.Create(fn)
		if err != nil {
			log.Fatalf("profile: could not create block profile %q: %v", fn, err)
		}
		runtime.SetBlockProfileRate(1)
		if !prof.Quiet {
			log.Printf("profile: block profiling enabled, %s", fn)
		}
		prof.closers = append(prof.closers, func() {
			pprof.Lookup("block").WriteTo(f, 0)
			f.Close()
			runtime.SetBlockProfileRate(0)
		})
	}

	if !prof.NoShutdownHook {
		go func() {
			c := make(chan os.Signal, 1)
			signal.Notify(c, os.Interrupt)
			<-c

			log.Println("profile: caught interrupt, stopping profiles")
			prof.Stop()

			os.Exit(0)
		}()
	}

	return prof
}
<commit_msg>Fix typo in CPUProfile comment<commit_after>// Package profile provides a simple way to manage runtime/pprof
// profiling of your Go application.
package profile

import (
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"runtime"
	"runtime/pprof"
)

type config struct {
	// Quiet suppresses informational messages during profiling.
	Quiet bool

	// CPUProfile controls if cpu profiling will be enabled.
	CPUProfile bool

	// MemProfile controls if memory profiling will be enabled.
	MemProfile bool

	// BlockProfile controls if block (contention) profiling will
	// be enabled.
	// It defaults to false.
	BlockProfile bool

	// ProfilePath controls the base path where various profiling
	// files are written. If blank, the base path will be generated
	// by ioutil.TempDir.
	ProfilePath string

	// NoShutdownHook controls whether the profiling package should
	// hook SIGINT to write profiles cleanly.
	NoShutdownHook bool
}

// NoShutdownHook controls whether the profiling package should
// hook SIGINT to write profiles cleanly.
// Programs with more sophisticated signal handling should set
// this to true and ensure the Stop() function returned from Start()
// is called during shutdown.
func NoShutdownHook(c *config) { c.NoShutdownHook = true }

// Quiet suppresses informational messages during profiling.
func Quiet(c *config) { c.Quiet = true }

const memProfileRate = 4096

func (c *config) NoProfiles() {
	c.CPUProfile = false
	c.MemProfile = false
	c.BlockProfile = false
}

// CPUProfile controls if cpu profiling will be enabled. It disables any previous profiling settings.
func CPUProfile(c *config) {
	c.NoProfiles()
	c.CPUProfile = true
}

// MemProfile controls if memory profiling will be enabled. It disables any previous profiling settings.
func MemProfile(c *config) {
	c.NoProfiles()
	c.MemProfile = true
}

// BlockProfile controls if block (contention) profiling will be enabled. It disables any previous profiling settings.
func BlockProfile(c *config) {
	c.NoProfiles()
	c.BlockProfile = true
}

// ProfilePath controls the base path where various profiling
// files are written. If blank, the base path will be generated
// by ioutil.TempDir.
func ProfilePath(path string) func(*config) {
	return func(c *config) {
		c.ProfilePath = path
	}
}

type profile struct {
	path string
	*config
	closers []func()
}

func (p *profile) Stop() {
	for _, c := range p.closers {
		c()
	}
}

func defaultOptions() []func(*config) {
	return []func(*config){
		CPUProfile,
		ProfilePath(""),
	}
}

// Start starts a new profiling session.
// The caller should call the Stop method on the value returned
// to cleanly stop profiling.
func Start(options ...func(*config)) interface {
	Stop()
} {
	options = append(defaultOptions(), options...)
	var cfg config
	for _, option := range options {
		option(&cfg)
	}

	path := cfg.ProfilePath
	var err error
	if path == "" {
		path, err = ioutil.TempDir("", "profile")
	} else {
		err = os.MkdirAll(path, 0777)
	}
	if err != nil {
		log.Fatalf("profile: could not create initial output directory: %v", err)
	}
	prof := &profile{
		path:   path,
		config: &cfg,
	}

	if prof.CPUProfile {
		fn := filepath.Join(prof.path, "cpu.pprof")
		f, err := os.Create(fn)
		if err != nil {
			log.Fatalf("profile: could not create cpu profile %q: %v", fn, err)
		}
		if !prof.Quiet {
			log.Printf("profile: cpu profiling enabled, %s", fn)
		}
		pprof.StartCPUProfile(f)
		prof.closers = append(prof.closers, func() {
			pprof.StopCPUProfile()
			f.Close()
		})
	}

	if prof.MemProfile {
		fn := filepath.Join(prof.path, "mem.pprof")
		f, err := os.Create(fn)
		if err != nil {
			log.Fatalf("profile: could not create memory profile %q: %v", fn, err)
		}
		old := runtime.MemProfileRate
		runtime.MemProfileRate = memProfileRate
		if !prof.Quiet {
			log.Printf("profile: memory profiling enabled, %s", fn)
		}
		prof.closers = append(prof.closers, func() {
			pprof.Lookup("heap").WriteTo(f, 0)
			f.Close()
			runtime.MemProfileRate = old
		})
	}

	if prof.BlockProfile {
		fn := filepath.Join(prof.path, "block.pprof")
		f, err := os.Create(fn)
		if err != nil {
			log.Fatalf("profile: could not create block profile %q: %v", fn, err)
		}
		runtime.SetBlockProfileRate(1)
		if !prof.Quiet {
			log.Printf("profile: block profiling enabled, %s", fn)
		}
		prof.closers = append(prof.closers, func() {
			pprof.Lookup("block").WriteTo(f, 0)
			f.Close()
			runtime.SetBlockProfileRate(0)
		})
	}

	if !prof.NoShutdownHook {
		go func() {
			c := make(chan os.Signal, 1)
			signal.Notify(c, os.Interrupt)
			<-c

			log.Println("profile: caught interrupt, stopping profiles")
			prof.Stop()

			os.Exit(0)
		}()
	}

	return prof
}
<|endoftext|>


<commit_before>package processout

import (
	"bytes"
	"encoding/json"
	"errors"
	"net/http"
	"net/url"
	"strings"
	"time"
)

// Projects manages the Project struct
type Projects struct {
	p *ProcessOut
}

type Project struct {
	// ID : ID of the project
	ID string `json:"id"`
	// Name : Name of the project
	Name string `json:"name"`
	// LogoURL : Name of the project
	LogoURL string `json:"logo_url"`
	// Email : Email of the project
	Email string `json:"email"`
	// CreatedAt : Date at which the project was created
	CreatedAt time.Time `json:"created_at"`
}

// GatewayConfigurations : Get all the gateway configurations of the project
func (s Projects) GatewayConfigurations(project *Project, options ...Options) ([]*GatewayConfiguration, error) {
	opt := Options{}
	if len(options) == 1 {
		opt = options[0]
	}
	if len(options) > 1 {
		panic("The options parameter should only be provided once.")
	}

	type Response struct {
		GatewayConfigurations []*GatewayConfiguration `json:"gateway_configurations"`
		Success               bool                    `json:"success"`
		Message               string                  `json:"message"`
	}

	body, err := json.Marshal(map[string]interface{}{
		"expand": opt.Expand,
	})
	if err != nil {
		return nil, err
	}

	path := "/projects/" + url.QueryEscape(project.ID) + "/gateway_configurations"

	req, err := http.NewRequest(
		"GET",
		Host+path,
		bytes.NewReader(body),
	)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("API-Version", s.p.APIVersion)
	req.Header.Set("Accept", "application/json")
	if opt.IdempotencyKey != "" {
		req.Header.Set("Idempotency-Key", opt.IdempotencyKey)
	}
	req.SetBasicAuth(s.p.projectID, s.p.projectSecret)

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	payload := &Response{}
	defer res.Body.Close()
	err = json.NewDecoder(res.Body).Decode(payload)
	if err != nil {
		return nil, err
	}

	if !payload.Success {
		return nil, errors.New(payload.Message)
	}
	return payload.GatewayConfigurations, nil
}

// Find : Find a project by its ID.
func (s Projects) Find(projectID string, options ...Options) (*Project, error) {
	opt := Options{}
	if len(options) == 1 {
		opt = options[0]
	}
	if len(options) > 1 {
		panic("The options parameter should only be provided once.")
	}

	type Response struct {
		Project `json:"project"`
		Success bool   `json:"success"`
		Message string `json:"message"`
	}

	body, err := json.Marshal(map[string]interface{}{
		"expand": opt.Expand,
	})
	if err != nil {
		return nil, err
	}

	path := "/projects/" + url.QueryEscape(projectID) + ""

	req, err := http.NewRequest(
		"GET",
		Host+path,
		bytes.NewReader(body),
	)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("API-Version", s.p.APIVersion)
	req.Header.Set("Accept", "application/json")
	if opt.IdempotencyKey != "" {
		req.Header.Set("Idempotency-Key", opt.IdempotencyKey)
	}
	req.SetBasicAuth(s.p.projectID, s.p.projectSecret)

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	payload := &Response{}
	defer res.Body.Close()
	err = json.NewDecoder(res.Body).Decode(payload)
	if err != nil {
		return nil, err
	}

	if !payload.Success {
		return nil, errors.New(payload.Message)
	}
	return &payload.Project, nil
}

// dummyProject is a dummy function that's only
// here because some files need specific packages and some don't.
// It's easier to include it for every file. In case you couldn't
// tell, everything is generated.
func dummyProject() {
	type dummy struct {
		a bytes.Buffer
		b json.RawMessage
		c http.File
		d strings.Reader
		e time.Time
		f url.URL
	}
	errors.New("")
}
<commit_msg>Fix project gateway configuration route<commit_after>package processout

import (
	"bytes"
	"encoding/json"
	"errors"
	"net/http"
	"net/url"
	"strings"
	"time"
)

// Projects manages the Project struct
type Projects struct {
	p *ProcessOut
}

type Project struct {
	// ID : ID of the project
	ID string `json:"id"`
	// Name : Name of the project
	Name string `json:"name"`
	// LogoURL : Name of the project
	LogoURL string `json:"logo_url"`
	// Email : Email of the project
	Email string `json:"email"`
	// CreatedAt : Date at which the project was created
	CreatedAt time.Time `json:"created_at"`
}

// GatewayConfigurations : Get all the gateway configurations of the project
func (s Projects) GatewayConfigurations(project *Project, options ...Options) ([]*GatewayConfiguration, error) {
	opt := Options{}
	if len(options) == 1 {
		opt = options[0]
	}
	if len(options) > 1 {
		panic("The options parameter should only be provided once.")
	}

	type Response struct {
		GatewayConfigurations []*GatewayConfiguration `json:"gateway_configurations"`
		Success               bool                    `json:"success"`
		Message               string                  `json:"message"`
	}

	body, err := json.Marshal(map[string]interface{}{
		"expand": opt.Expand,
	})
	if err != nil {
		return nil, err
	}

	path := "/projects/" + url.QueryEscape(project.ID) + "/gateway-configurations"

	req, err := http.NewRequest(
		"GET",
		Host+path,
		bytes.NewReader(body),
	)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("API-Version", s.p.APIVersion)
	req.Header.Set("Accept", "application/json")
	if opt.IdempotencyKey != "" {
		req.Header.Set("Idempotency-Key", opt.IdempotencyKey)
	}
	req.SetBasicAuth(s.p.projectID, s.p.projectSecret)

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	payload := &Response{}
	defer res.Body.Close()
	err = json.NewDecoder(res.Body).Decode(payload)
	if err != nil {
		return nil, err
	}

	if !payload.Success {
		return nil, errors.New(payload.Message)
	}
	return payload.GatewayConfigurations, nil
}

// Find : Find a project by its ID.
func (s Projects) Find(projectID string, options ...Options) (*Project, error) {
	opt := Options{}
	if len(options) == 1 {
		opt = options[0]
	}
	if len(options) > 1 {
		panic("The options parameter should only be provided once.")
	}

	type Response struct {
		Project `json:"project"`
		Success bool   `json:"success"`
		Message string `json:"message"`
	}

	body, err := json.Marshal(map[string]interface{}{
		"expand": opt.Expand,
	})
	if err != nil {
		return nil, err
	}

	path := "/projects/" + url.QueryEscape(projectID) + ""

	req, err := http.NewRequest(
		"GET",
		Host+path,
		bytes.NewReader(body),
	)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("API-Version", s.p.APIVersion)
	req.Header.Set("Accept", "application/json")
	if opt.IdempotencyKey != "" {
		req.Header.Set("Idempotency-Key", opt.IdempotencyKey)
	}
	req.SetBasicAuth(s.p.projectID, s.p.projectSecret)

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	payload := &Response{}
	defer res.Body.Close()
	err = json.NewDecoder(res.Body).Decode(payload)
	if err != nil {
		return nil, err
	}

	if !payload.Success {
		return nil, errors.New(payload.Message)
	}
	return &payload.Project, nil
}

// dummyProject is a dummy function that's only
// here because some files need specific packages and some don't.
// It's easier to include it for every file. In case you couldn't
// tell, everything is generated.
func dummyProject() {
	type dummy struct {
		a bytes.Buffer
		b json.RawMessage
		c http.File
		d strings.Reader
		e time.Time
		f url.URL
	}
	errors.New("")
}
<|endoftext|>