<commit_before>package duktape

import "reflect"
import "testing"

func TestEvalString(t *testing.T) {
	ctx := NewContext()
	ctx.EvalString(`"Golang love Duktape!"`)
	expect(t, Type(ctx.GetType(-1)).IsString(), true)
	expect(t, ctx.GetString(-1), "Golang love Duktape!")
	ctx.DestroyHeap()
}

func TestEvalFunc(t *testing.T) {
	ctx := NewContext()
	ctx.PevalString(`(function (x) { return x + x; })`)
	expect(t, ctx.IsCallable(-1), true)
	expect(t, Type(ctx.GetType(-1)).IsObject(), true)
	ctx.PushInt(5)
	ctx.Pcall(1)
	expect(t, ctx.GetInt(-1), 10)
	ctx.DestroyHeap()
}

func TestEvalWith(t *testing.T) {
	ctx := NewContext()

	obj := MethodSuite{
		"hi": func(d *Context) int {
			d.PushString("hi!")
			return 1
		},
	}
	err := ctx.EvalWith("(function(o) { return o.hi(1, 2, 3) })", obj)
	expect(t, err, nil)

	actual := ctx.GetString(-1)

	expect(t, actual, "hi!")

	ctx.DestroyHeap()
}

// from duktape examples

func TestMyAddTwo(t *testing.T) {
	obj := MethodSuite{
		"add": func(d *Context) int {
			top := d.GetTop()
			a := d.GetNumber(top - 2)
			b := d.GetNumber(top - 1)
			d.PushNumber(a + b)
			return 1
		},
	}

	ctx := NewContext()
	ctx.PushGlobalObject()

	// Hmm... a property value can outlive an object. look out!
	ctx.EvalWith("(function(o) { return o.add })", obj)

	ctx.PutPropString(-2, "adder")

	ctx.PevalString(`adder(2, 3);`)
	res := ctx.GetNumber(-1)
	ctx.Pop()
	expect(t, res, float64(5))
}

func expect(t *testing.T, a interface{}, b interface{}) {
	if a != b {
		t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
	}
}
<commit_msg>test shared state between closures in a method suite<commit_after>package duktape

import "reflect"
import "testing"

func TestEvalString(t *testing.T) {
	ctx := NewContext()
	ctx.EvalString(`"Golang love Duktape!"`)
	expect(t, Type(ctx.GetType(-1)).IsString(), true)
	expect(t, ctx.GetString(-1), "Golang love Duktape!")
	ctx.DestroyHeap()
}

func TestEvalFunc(t *testing.T) {
	ctx := NewContext()
	ctx.PevalString(`(function (x) { return x + x; })`)
	expect(t, ctx.IsCallable(-1), true)
	expect(t, Type(ctx.GetType(-1)).IsObject(), true)
	ctx.PushInt(5)
	ctx.Pcall(1)
	expect(t, ctx.GetInt(-1), 10)
	ctx.DestroyHeap()
}

func TestEvalWith(t *testing.T) {
	ctx := NewContext()

	obj := MethodSuite{
		"hi": func(d *Context) int {
			d.PushString("hi!")
			return 1
		},
	}
	err := ctx.EvalWith("(function(o) { return o.hi(1, 2, 3) })", obj)
	expect(t, err, nil)

	actual := ctx.GetString(-1)

	expect(t, actual, "hi!")

	ctx.DestroyHeap()
}

// from duktape examples

func TestMyAddTwo(t *testing.T) {
	obj := MethodSuite{
		"add": func(d *Context) int {
			top := d.GetTop()
			a := d.GetNumber(top - 2)
			b := d.GetNumber(top - 1)
			d.PushNumber(a + b)
			return 1
		},
	}

	ctx := NewContext()
	ctx.PushGlobalObject()

	// Hmm... a property value can outlive an object. look out!
	ctx.EvalWith("(function(o) { return o.add })", obj)

	ctx.PutPropString(-2, "adder")

	ctx.PevalString(`adder(2, 3);`)
	res := ctx.GetNumber(-1)
	ctx.Pop()
	expect(t, res, float64(5))
	ctx.DestroyHeap()
}

func TestGoClosure(t *testing.T) {
	sharedState := 0
	obj := MethodSuite{
		"inc": func(d *Context) int {
			sharedState++
			d.PushInt(sharedState)
			return 1
		},
		"dec": func(d *Context) int {
			sharedState--
			d.PushInt(sharedState)
			return 1
		},
	}

	ctx := NewContext()

	ctx.EvalWith(`
            (function(o) {
                 o.inc();
                 o.inc();
                 o.dec();
                 o.inc();
                 return o.inc();
             })`, obj)
	res := ctx.GetNumber(-1)
	expect(t, res, float64(3))
	ctx.DestroyHeap()
}

func expect(t *testing.T, a interface{}, b interface{}) {
	if a != b {
		t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
	}
}
<|endoftext|>


<commit_before>package storage

import (
	"context"
	"fmt"
	"io"
	"time"

	"github.com/sirupsen/logrus"

	"github.com/ovh/cds/engine/cdn/item"
	"github.com/ovh/cds/engine/gorpmapper"
	"github.com/ovh/cds/sdk"
	"github.com/ovh/cds/sdk/log"
)

func (x *RunningStorageUnits) Run(ctx context.Context, s StorageUnit) error {
	s.Lock()
	defer s.Unlock()
	_, err := LoadUnitByID(ctx, x.m, x.db, s.ID())
	if err != nil {
		return err
	}

	// Load items to sync
	itemIDs, err := LoadAllItemIDUnknownByUnitOrderByUnitID(x.db, s.ID(), x.Buffer.ID(), 100)
	if err != nil {
		return err
	}

	if len(itemIDs) > 0 {
		log.Info(ctx, "storage.Run> unit %s has %d items to sync", s.Name(), len(itemIDs))
	}

	for _, id := range itemIDs {
		tx, err := x.db.Begin()
		if err != nil {
			return err
		}

		it, err := item.LoadAndLockByID(ctx, x.m, tx, id, gorpmapper.GetOptions.WithDecryption)
		if err != nil {
			if !sdk.ErrorIs(err, sdk.ErrNotFound) {
				log.ErrorWithFields(ctx, logrus.Fields{"stack_trace": fmt.Sprintf("%+v", err)}, "%s", err)
			}
			tx.Rollback() // nolint
			continue
		}

		if err := x.runItem(ctx, tx, s, it); err != nil {
			log.ErrorWithFields(ctx, logrus.Fields{"stack_trace": fmt.Sprintf("%+v", err)}, "%s", err)
			tx.Rollback() // nolint
			continue
		}

		if err := tx.Commit(); err != nil {
			err = sdk.WrapError(err, "unable to commit txt")
			log.ErrorWithFields(ctx, logrus.Fields{"stack_trace": fmt.Sprintf("%+v", err)}, "%s", err)
			tx.Rollback() // nolint
			continue
		}
	}
	return nil
}

func (x *RunningStorageUnits) runItem(ctx context.Context, tx gorpmapper.SqlExecutorWithTx, dest StorageUnit, item *sdk.CDNItem) error {
	t0 := time.Now()
	log.Debug("storage.runItem(%s, %s)", dest.Name(), item.ID)
	defer func() {
		log.Debug("storage.runItem(%s, %s): %fs", dest.Name(), item.ID, time.Since(t0).Seconds())
	}()

	iu, err := x.NewItemUnit(ctx, dest, item)
	if err != nil {
		return err
	}
	iu.Item = item

	// Save in database that the item is complete for the storage unit
	if err := InsertItemUnit(ctx, x.m, tx, iu); err != nil {
		return err
	}

	// Reload with decryption
	iu, err = LoadItemUnitByID(ctx, x.m, tx, iu.ID, gorpmapper.GetOptions.WithDecryption)
	if err != nil {
		return err
	}

	// Prepare the destination
	writer, err := dest.NewWriter(ctx, *iu)
	if err != nil {
		return err
	}
	if writer == nil {
		return nil
	}

	source, err := x.GetSource(ctx, item)
	if err != nil {
		return err
	}

	reader, err := source.NewReader(ctx)
	if err != nil {
		return err
	}

	chanError := make(chan error)
	pr, pw := io.Pipe()

	go func() {
		defer pw.Close()
		if err := source.Read(reader, pw); err != nil {
			chanError <- err
		}
		close(chanError)
	}()

	if err := dest.Write(*iu, pr, writer); err != nil {
		_ = pr.Close()
		_ = reader.Close()
		_ = writer.Close()
		return err
	}

	if err := pr.Close(); err != nil {
		_ = reader.Close()
		_ = writer.Close()
		return sdk.WithStack(err)
	}

	if err := reader.Close(); err != nil {
		_ = writer.Close()
		return sdk.WithStack(err)
	}

	_ = writer.Close()

	for err := range chanError {
		if err != nil {
			return err
		}
	}

	log.Info(ctx, "item %s has been pushed to %s", item.ID, dest.Name())
	return nil
}

func (x *RunningStorageUnits) NewItemUnit(_ context.Context, su Interface, i *sdk.CDNItem) (*sdk.CDNItemUnit, error) {
	suloc, is := su.(StorageUnitWithLocator)
	var loc string
	if is {
		var err error
		loc, err = suloc.NewLocator(i.Hash)
		if err != nil {
			return nil, sdk.WrapError(err, "unable to compyte convergent locator")
		}
	}

	var iu = sdk.CDNItemUnit{
		ItemID:       i.ID,
		UnitID:       su.ID(),
		LastModified: time.Now(),
		Locator:      loc,
		Item:         i,
	}

	return &iu, nil
}
<commit_msg>fix(cdn):  conflict during backend synchronization (#5458)<commit_after>package storage

import (
	"context"
	"fmt"
	"io"
	"time"

	"github.com/sirupsen/logrus"

	"github.com/ovh/cds/engine/cdn/item"
	"github.com/ovh/cds/engine/gorpmapper"
	"github.com/ovh/cds/sdk"
	"github.com/ovh/cds/sdk/log"
)

func (x *RunningStorageUnits) Run(ctx context.Context, s StorageUnit) error {
	s.Lock()
	defer s.Unlock()
	_, err := LoadUnitByID(ctx, x.m, x.db, s.ID())
	if err != nil {
		return err
	}

	// Load items to sync
	itemIDs, err := LoadAllItemIDUnknownByUnitOrderByUnitID(x.db, s.ID(), x.Buffer.ID(), 100)
	if err != nil {
		return err
	}

	if len(itemIDs) > 0 {
		log.Info(ctx, "storage.Run> unit %s has %d items to sync", s.Name(), len(itemIDs))
	}

	for _, id := range itemIDs {
		tx, err := x.db.Begin()
		if err != nil {
			return err
		}

		it, err := item.LoadAndLockByID(ctx, x.m, tx, id, gorpmapper.GetOptions.WithDecryption)
		if err != nil {
			if !sdk.ErrorIs(err, sdk.ErrNotFound) {
				log.ErrorWithFields(ctx, logrus.Fields{"stack_trace": fmt.Sprintf("%+v", err)}, "%s", err)
			}
			tx.Rollback() // nolint
			continue
		}

		_, err = LoadItemUnitByUnit(ctx, x.m, tx, s.ID(), id)
		if err == nil {
			_ = tx.Rollback()
			continue
		}
		if !sdk.ErrorIs(err, sdk.ErrNotFound) {
			log.ErrorWithFields(ctx, logrus.Fields{"stack_trace": fmt.Sprintf("%+v", err)}, "%s", err)
			_ = tx.Rollback()
			continue
		}

		if err := x.runItem(ctx, tx, s, it); err != nil {
			log.ErrorWithFields(ctx, logrus.Fields{"stack_trace": fmt.Sprintf("%+v", err)}, "%s", err)
			tx.Rollback() // nolint
			continue
		}

		if err := tx.Commit(); err != nil {
			err = sdk.WrapError(err, "unable to commit txt")
			log.ErrorWithFields(ctx, logrus.Fields{"stack_trace": fmt.Sprintf("%+v", err)}, "%s", err)
			tx.Rollback() // nolint
			continue
		}
	}
	return nil
}

func (x *RunningStorageUnits) runItem(ctx context.Context, tx gorpmapper.SqlExecutorWithTx, dest StorageUnit, item *sdk.CDNItem) error {
	t0 := time.Now()
	log.Debug("storage.runItem(%s, %s)", dest.Name(), item.ID)
	defer func() {
		log.Debug("storage.runItem(%s, %s): %fs", dest.Name(), item.ID, time.Since(t0).Seconds())
	}()

	iu, err := x.NewItemUnit(ctx, dest, item)
	if err != nil {
		return err
	}
	iu.Item = item

	// Save in database that the item is complete for the storage unit
	if err := InsertItemUnit(ctx, x.m, tx, iu); err != nil {
		return err
	}

	// Reload with decryption
	iu, err = LoadItemUnitByID(ctx, x.m, tx, iu.ID, gorpmapper.GetOptions.WithDecryption)
	if err != nil {
		return err
	}

	// Prepare the destination
	writer, err := dest.NewWriter(ctx, *iu)
	if err != nil {
		return err
	}
	if writer == nil {
		return nil
	}

	source, err := x.GetSource(ctx, item)
	if err != nil {
		return err
	}

	reader, err := source.NewReader(ctx)
	if err != nil {
		return err
	}

	chanError := make(chan error)
	pr, pw := io.Pipe()

	go func() {
		defer pw.Close()
		if err := source.Read(reader, pw); err != nil {
			chanError <- err
		}
		close(chanError)
	}()

	if err := dest.Write(*iu, pr, writer); err != nil {
		_ = pr.Close()
		_ = reader.Close()
		_ = writer.Close()
		return err
	}

	if err := pr.Close(); err != nil {
		_ = reader.Close()
		_ = writer.Close()
		return sdk.WithStack(err)
	}

	if err := reader.Close(); err != nil {
		_ = writer.Close()
		return sdk.WithStack(err)
	}

	_ = writer.Close()

	for err := range chanError {
		if err != nil {
			return err
		}
	}

	log.Info(ctx, "item %s has been pushed to %s", item.ID, dest.Name())
	return nil
}

func (x *RunningStorageUnits) NewItemUnit(_ context.Context, su Interface, i *sdk.CDNItem) (*sdk.CDNItemUnit, error) {
	suloc, is := su.(StorageUnitWithLocator)
	var loc string
	if is {
		var err error
		loc, err = suloc.NewLocator(i.Hash)
		if err != nil {
			return nil, sdk.WrapError(err, "unable to compyte convergent locator")
		}
	}

	var iu = sdk.CDNItemUnit{
		ItemID:       i.ID,
		UnitID:       su.ID(),
		LastModified: time.Now(),
		Locator:      loc,
		Item:         i,
	}

	return &iu, nil
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"). You
 * may not use this file except in compliance with the License. A copy of
 * the License is located at
 *
 * 	http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file 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 ecr

import (
	"context"
	"encoding/json"
	"errors"
	"strings"
	"sync"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ecr"
	ecrsdk "github.com/aws/aws-sdk-go/service/ecr"
	"github.com/containerd/containerd/images"
	"github.com/containerd/containerd/log"
	"github.com/containerd/containerd/reference"
	"github.com/containerd/containerd/remotes"
	"github.com/containerd/containerd/remotes/docker"
	"github.com/opencontainers/go-digest"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

var unimplemented = errors.New("unimplemented")

type ecrResolver struct {
	session     *session.Session
	clients     map[string]ecrAPI
	clientsLock sync.Mutex
	tracker     docker.StatusTracker
}

// ResolverOption represents a functional option for configuring the ECR
// Resolver
type ResolverOption func(*ResolverOptions) error

// ResolverOptions represents available options for configuring the ECR Resolver
type ResolverOptions struct {
	// Session is used for configuring the ECR client.  If not specified, a
	// generic session is used.
	Session *session.Session
	// Tracker is used to track uploads to ECR.  If not specified, an in-memory
	// tracker is used instead.
	Tracker docker.StatusTracker
}

// WithSession is a ResolverOption to use a specific AWS session.Session
func WithSession(session *session.Session) ResolverOption {
	return func(options *ResolverOptions) error {
		options.Session = session
		return nil
	}
}

// WithTracker is a ResolverOption to use a specific docker.Tracker
func WithTracker(tracker docker.StatusTracker) ResolverOption {
	return func(options *ResolverOptions) error {
		options.Tracker = tracker
		return nil
	}
}

func NewResolver(options ...ResolverOption) (remotes.Resolver, error) {
	resolverOptions := &ResolverOptions{}
	for _, option := range options {
		err := option(resolverOptions)
		if err != nil {
			return nil, err
		}
	}
	if resolverOptions.Session == nil {
		awsSession, err := session.NewSession()
		if err != nil {
			return nil, err
		}
		resolverOptions.Session = awsSession
	}
	if resolverOptions.Tracker == nil {
		resolverOptions.Tracker = docker.NewInMemoryTracker()
	}
	if resolverOptions.Session == nil {

	}
	return &ecrResolver{
		session: resolverOptions.Session,
		clients: map[string]ecrAPI{},
		tracker: resolverOptions.Tracker,
	}, nil
}

func (r *ecrResolver) Resolve(ctx context.Context, ref string) (string, ocispec.Descriptor, error) {
	ecrSpec, err := ParseRef(ref)
	if err != nil {
		return "", ocispec.Descriptor{}, err
	}

	if ecrSpec.Object == "" {
		return "", ocispec.Descriptor{}, reference.ErrObjectRequired
	}

	batchGetImageInput := &ecr.BatchGetImageInput{
		RegistryId:         aws.String(ecrSpec.Registry()),
		RepositoryName:     aws.String(ecrSpec.Repository),
		ImageIds:           []*ecr.ImageIdentifier{ecrSpec.ImageID()},
		AcceptedMediaTypes: []*string{aws.String(images.MediaTypeDockerSchema2Manifest)},
	}

	client := r.getClient(ecrSpec.Region())

	batchGetImageOutput, err := client.BatchGetImageWithContext(ctx, batchGetImageInput)
	if err != nil {
		log.G(ctx).
			WithField("ref", ref).
			WithError(err).
			Warn("Failed while calling BatchGetImage")
		return "", ocispec.Descriptor{}, err
	}
	log.G(ctx).
		WithField("ref", ref).
		WithField("batchGetImageOutput", batchGetImageOutput).
		Debug("ecr.resolver.resolve")

	var ecrImage *ecr.Image
	if len(batchGetImageOutput.Images) == 0 {
		return "", ocispec.Descriptor{}, reference.ErrInvalid
	}
	ecrImage = batchGetImageOutput.Images[0]
	mediaType := parseImageManifestMediaType(ctx, aws.StringValue(ecrImage.ImageManifest))
	log.G(ctx).
		WithField("ref", ref).
		WithField("media type", mediaType).
		Debug("ecr.resolver.resolve")
	desc := ocispec.Descriptor{
		Digest:    digest.Digest(aws.StringValue(ecrImage.ImageId.ImageDigest)),
		MediaType: mediaType,
		Size:      int64(len(aws.StringValue(ecrImage.ImageManifest))),
	}

	return ecrSpec.Canonical(), desc, nil
}

func (r *ecrResolver) getClient(region string) ecrAPI {
	r.clientsLock.Lock()
	defer r.clientsLock.Unlock()
	if _, ok := r.clients[region]; !ok {
		r.clients[region] = ecrsdk.New(r.session, &aws.Config{Region: aws.String(region)})
	}
	return r.clients[region]
}

type manifestContent struct {
	SchemaVersion int64         `json:"schemaVersion"`
	Signatures    []interface{} `json:"signatures,omitempty"`
	MediaType     string        `json:"mediaType,omitempty"`
}

func parseImageManifestMediaType(ctx context.Context, body string) string {
	var manifest manifestContent
	err := json.Unmarshal([]byte(body), &manifest)
	if err != nil {
		log.G(ctx).WithError(err).Warn("ecr.resolver.resolve: could not parse manifest")
		// default to schema 2 for now
		return images.MediaTypeDockerSchema2Manifest
	}
	if manifest.SchemaVersion == 2 {
		return manifest.MediaType
	} else if manifest.SchemaVersion == 1 {
		if len(manifest.Signatures) == 0 {
			// unsigned
			return "application/vnd.docker.distribution.manifest.v1+json"
		} else {
			return images.MediaTypeDockerSchema1Manifest
		}
	}

	return ""
}

func (r *ecrResolver) Fetcher(ctx context.Context, ref string) (remotes.Fetcher, error) {
	log.G(ctx).WithField("ref", ref).Debug("ecr.resolver.fetcher")
	ecrSpec, err := ParseRef(ref)
	if err != nil {
		return nil, err
	}
	return &ecrFetcher{
		ecrBase{
			client:  r.getClient(ecrSpec.Region()),
			ecrSpec: ecrSpec,
		},
	}, nil
}

func (r *ecrResolver) Pusher(ctx context.Context, ref string) (remotes.Pusher, error) {
	log.G(ctx).WithField("ref", ref).Debug("ecr.resolver.pusher")
	ecrSpec, err := ParseRef(ref)
	if err != nil {
		return nil, err
	}
	// TODO block pushing by digest since that's not allowed
	// see containerd/remotes/docker/resolver.go:218

	if ecrSpec.Object != "" && strings.Contains(ecrSpec.Object, "@") {
		return nil, errors.New("pusher: cannot use digest reference for push location")
	}

	return &ecrPusher{
		ecrBase: ecrBase{
			client:  r.getClient(ecrSpec.Region()),
			ecrSpec: ecrSpec,
		},
		tracker: r.tracker,
	}, nil
}
<commit_msg>resolver: remove empty conditional<commit_after>/*
 * Copyright 2017-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"). You
 * may not use this file except in compliance with the License. A copy of
 * the License is located at
 *
 * 	http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file 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 ecr

import (
	"context"
	"encoding/json"
	"errors"
	"strings"
	"sync"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ecr"
	ecrsdk "github.com/aws/aws-sdk-go/service/ecr"
	"github.com/containerd/containerd/images"
	"github.com/containerd/containerd/log"
	"github.com/containerd/containerd/reference"
	"github.com/containerd/containerd/remotes"
	"github.com/containerd/containerd/remotes/docker"
	"github.com/opencontainers/go-digest"
	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)

var unimplemented = errors.New("unimplemented")

type ecrResolver struct {
	session     *session.Session
	clients     map[string]ecrAPI
	clientsLock sync.Mutex
	tracker     docker.StatusTracker
}

// ResolverOption represents a functional option for configuring the ECR
// Resolver
type ResolverOption func(*ResolverOptions) error

// ResolverOptions represents available options for configuring the ECR Resolver
type ResolverOptions struct {
	// Session is used for configuring the ECR client.  If not specified, a
	// generic session is used.
	Session *session.Session
	// Tracker is used to track uploads to ECR.  If not specified, an in-memory
	// tracker is used instead.
	Tracker docker.StatusTracker
}

// WithSession is a ResolverOption to use a specific AWS session.Session
func WithSession(session *session.Session) ResolverOption {
	return func(options *ResolverOptions) error {
		options.Session = session
		return nil
	}
}

// WithTracker is a ResolverOption to use a specific docker.Tracker
func WithTracker(tracker docker.StatusTracker) ResolverOption {
	return func(options *ResolverOptions) error {
		options.Tracker = tracker
		return nil
	}
}

func NewResolver(options ...ResolverOption) (remotes.Resolver, error) {
	resolverOptions := &ResolverOptions{}
	for _, option := range options {
		err := option(resolverOptions)
		if err != nil {
			return nil, err
		}
	}
	if resolverOptions.Session == nil {
		awsSession, err := session.NewSession()
		if err != nil {
			return nil, err
		}
		resolverOptions.Session = awsSession
	}
	if resolverOptions.Tracker == nil {
		resolverOptions.Tracker = docker.NewInMemoryTracker()
	}
	return &ecrResolver{
		session: resolverOptions.Session,
		clients: map[string]ecrAPI{},
		tracker: resolverOptions.Tracker,
	}, nil
}

func (r *ecrResolver) Resolve(ctx context.Context, ref string) (string, ocispec.Descriptor, error) {
	ecrSpec, err := ParseRef(ref)
	if err != nil {
		return "", ocispec.Descriptor{}, err
	}

	if ecrSpec.Object == "" {
		return "", ocispec.Descriptor{}, reference.ErrObjectRequired
	}

	batchGetImageInput := &ecr.BatchGetImageInput{
		RegistryId:         aws.String(ecrSpec.Registry()),
		RepositoryName:     aws.String(ecrSpec.Repository),
		ImageIds:           []*ecr.ImageIdentifier{ecrSpec.ImageID()},
		AcceptedMediaTypes: []*string{aws.String(images.MediaTypeDockerSchema2Manifest)},
	}

	client := r.getClient(ecrSpec.Region())

	batchGetImageOutput, err := client.BatchGetImageWithContext(ctx, batchGetImageInput)
	if err != nil {
		log.G(ctx).
			WithField("ref", ref).
			WithError(err).
			Warn("Failed while calling BatchGetImage")
		return "", ocispec.Descriptor{}, err
	}
	log.G(ctx).
		WithField("ref", ref).
		WithField("batchGetImageOutput", batchGetImageOutput).
		Debug("ecr.resolver.resolve")

	var ecrImage *ecr.Image
	if len(batchGetImageOutput.Images) == 0 {
		return "", ocispec.Descriptor{}, reference.ErrInvalid
	}
	ecrImage = batchGetImageOutput.Images[0]
	mediaType := parseImageManifestMediaType(ctx, aws.StringValue(ecrImage.ImageManifest))
	log.G(ctx).
		WithField("ref", ref).
		WithField("media type", mediaType).
		Debug("ecr.resolver.resolve")
	desc := ocispec.Descriptor{
		Digest:    digest.Digest(aws.StringValue(ecrImage.ImageId.ImageDigest)),
		MediaType: mediaType,
		Size:      int64(len(aws.StringValue(ecrImage.ImageManifest))),
	}

	return ecrSpec.Canonical(), desc, nil
}

func (r *ecrResolver) getClient(region string) ecrAPI {
	r.clientsLock.Lock()
	defer r.clientsLock.Unlock()
	if _, ok := r.clients[region]; !ok {
		r.clients[region] = ecrsdk.New(r.session, &aws.Config{Region: aws.String(region)})
	}
	return r.clients[region]
}

type manifestContent struct {
	SchemaVersion int64         `json:"schemaVersion"`
	Signatures    []interface{} `json:"signatures,omitempty"`
	MediaType     string        `json:"mediaType,omitempty"`
}

func parseImageManifestMediaType(ctx context.Context, body string) string {
	var manifest manifestContent
	err := json.Unmarshal([]byte(body), &manifest)
	if err != nil {
		log.G(ctx).WithError(err).Warn("ecr.resolver.resolve: could not parse manifest")
		// default to schema 2 for now
		return images.MediaTypeDockerSchema2Manifest
	}
	if manifest.SchemaVersion == 2 {
		return manifest.MediaType
	} else if manifest.SchemaVersion == 1 {
		if len(manifest.Signatures) == 0 {
			// unsigned
			return "application/vnd.docker.distribution.manifest.v1+json"
		} else {
			return images.MediaTypeDockerSchema1Manifest
		}
	}

	return ""
}

func (r *ecrResolver) Fetcher(ctx context.Context, ref string) (remotes.Fetcher, error) {
	log.G(ctx).WithField("ref", ref).Debug("ecr.resolver.fetcher")
	ecrSpec, err := ParseRef(ref)
	if err != nil {
		return nil, err
	}
	return &ecrFetcher{
		ecrBase{
			client:  r.getClient(ecrSpec.Region()),
			ecrSpec: ecrSpec,
		},
	}, nil
}

func (r *ecrResolver) Pusher(ctx context.Context, ref string) (remotes.Pusher, error) {
	log.G(ctx).WithField("ref", ref).Debug("ecr.resolver.pusher")
	ecrSpec, err := ParseRef(ref)
	if err != nil {
		return nil, err
	}
	// TODO block pushing by digest since that's not allowed
	// see containerd/remotes/docker/resolver.go:218

	if ecrSpec.Object != "" && strings.Contains(ecrSpec.Object, "@") {
		return nil, errors.New("pusher: cannot use digest reference for push location")
	}

	return &ecrPusher{
		ecrBase: ecrBase{
			client:  r.getClient(ecrSpec.Region()),
			ecrSpec: ecrSpec,
		},
		tracker: r.tracker,
	}, nil
}
<|endoftext|>


<commit_before>package docker

import (
	"github.com/libkermit/docker/test"
)

type kermitClient struct {
	test.NopClient
}
<commit_msg>Removed empty test file<commit_after><|endoftext|>


<commit_before>package edit

import (
	"container/list"
	"fmt"
	"strings"
	"unicode/utf8"

	"github.com/elves/elvish/edit/ui"
	"github.com/elves/elvish/util"
)

// listing implements a listing mode that supports the notion of selecting an
// entry and filtering entries.
type listing struct {
	typ         ModeType
	provider    listingProvider
	selected    int
	filter      string
	pagesize    int
	headerWidth int
}

type listingProvider interface {
	Len() int
	Show(i int) (string, ui.Styled)
	Filter(filter string) int
	Accept(i int, ed *Editor)
	ModeTitle(int) string
}

type Placeholderer interface {
	Placeholder() string
}

func newListing(t ModeType, p listingProvider) listing {
	l := listing{t, p, 0, "", 0, 0}
	l.changeFilter("")
	for i := 0; i < p.Len(); i++ {
		header, _ := p.Show(i)
		width := util.Wcswidth(header)
		if l.headerWidth < width {
			l.headerWidth = width
		}
	}
	return l
}

func (l *listing) Mode() ModeType {
	return l.typ
}

func (l *listing) ModeLine() renderer {
	return modeLineRenderer{l.provider.ModeTitle(l.selected), l.filter}
}

func (l *listing) List(maxHeight int) renderer {
	n := l.provider.Len()
	if n == 0 {
		var ph string
		if pher, ok := l.provider.(Placeholderer); ok {
			ph = pher.Placeholder()
		} else {
			ph = "(no result)"
		}
		return placeholderRenderer(ph)
	}

	// Collect the entries to show. We start from the selected entry and extend
	// in both directions alternatingly. The entries are split into lines and
	// then collected in a list.
	low := l.selected
	if low == -1 {
		low = 0
	}
	high := low
	height := 0
	var listOfLines list.List
	getEntry := func(i int) []ui.Styled {
		header, content := l.provider.Show(i)
		lines := strings.Split(content.Text, "\n")
		styles := content.Styles
		if i == l.selected {
			styles = append(styles, styleForSelected...)
		}
		styleds := make([]ui.Styled, len(lines))
		for i, line := range lines {
			if l.headerWidth > 0 {
				if i == 0 {
					line = fmt.Sprintf("%*s %s", l.headerWidth, header, line)
				} else {
					line = fmt.Sprintf("%*s %s", l.headerWidth, "", line)
				}
			}
			styleds[i] = ui.Styled{line, styles}
		}
		return styleds
	}
	// We start by extending high, so that the first entry to include is
	// l.selected.
	extendLow := false
	lastShownIncomplete := false
	for height < maxHeight && !(low == 0 && high == n) {
		var i int
		if (extendLow && low > 0) || high == n {
			low--

			entry := getEntry(low)
			// Prepend at most the last (height - maxHeight) lines.
			for i = len(entry) - 1; i >= 0 && height < maxHeight; i-- {
				listOfLines.PushFront(entry[i])
				height++
			}
			if i >= 0 {
				lastShownIncomplete = true
			}
		} else {
			entry := getEntry(high)
			// Append at most the first (height - maxHeight) lines.
			for i = 0; i < len(entry) && height < maxHeight; i++ {
				listOfLines.PushBack(entry[i])
				height++
			}
			if i < len(entry) {
				lastShownIncomplete = true
			}

			high++
		}
		extendLow = !extendLow
	}

	l.pagesize = high - low

	// Convert the List to a slice.
	lines := make([]ui.Styled, 0, listOfLines.Len())
	for p := listOfLines.Front(); p != nil; p = p.Next() {
		lines = append(lines, p.Value.(ui.Styled))
	}

	ls := listingRenderer{lines}
	if low > 0 || high < n || lastShownIncomplete {
		// Need scrollbar
		return listingWithScrollBarRenderer{ls, n, low, high, height}
	}
	return ls
}

func writeHorizontalScrollbar(b *buffer, n, low, high, width int) {
	slow, shigh := findScrollInterval(n, low, high, width)
	for i := 0; i < width; i++ {
		if slow <= i && i < shigh {
			b.write(' ', styleForScrollBarThumb.String())
		} else {
			b.write('━', styleForScrollBarArea.String())
		}
	}
}

func renderScrollbar(n, low, high, height int) *buffer {
	slow, shigh := findScrollInterval(n, low, high, height)
	// Logger.Printf("low = %d, high = %d, n = %d, slow = %d, shigh = %d", low, high, n, slow, shigh)
	b := newBuffer(1)
	for i := 0; i < height; i++ {
		if i > 0 {
			b.newline()
		}
		if slow <= i && i < shigh {
			b.write(' ', styleForScrollBarThumb.String())
		} else {
			b.write('│', styleForScrollBarArea.String())
		}
	}
	return b
}

func findScrollInterval(n, low, high, height int) (int, int) {
	f := func(i int) int {
		return int(float64(i)/float64(n)*float64(height) + 0.5)
	}
	scrollLow, scrollHigh := f(low), f(high)
	if scrollLow == scrollHigh {
		if scrollHigh == high {
			scrollLow--
		} else {
			scrollHigh++
		}
	}
	return scrollLow, scrollHigh
}

func (l *listing) changeFilter(newfilter string) {
	l.filter = newfilter
	l.selected = l.provider.Filter(newfilter)
}

func (l *listing) backspace() bool {
	_, size := utf8.DecodeLastRuneInString(l.filter)
	if size > 0 {
		l.changeFilter(l.filter[:len(l.filter)-size])
		return true
	}
	return false
}

func (l *listing) up(cycle bool) {
	n := l.provider.Len()
	if n == 0 {
		return
	}
	l.selected--
	if l.selected == -1 {
		if cycle {
			l.selected += n
		} else {
			l.selected++
		}
	}
}

func (l *listing) pageUp() {
	n := l.provider.Len()
	if n == 0 {
		return
	}
	l.selected -= l.pagesize
	if l.selected < 0 {
		l.selected = 0
	}
}

func (l *listing) down(cycle bool) {
	n := l.provider.Len()
	if n == 0 {
		return
	}
	l.selected++
	if l.selected == n {
		if cycle {
			l.selected -= n
		} else {
			l.selected--
		}
	}
}

func (l *listing) pageDown() {
	n := l.provider.Len()
	if n == 0 {
		return
	}
	l.selected += l.pagesize
	if l.selected >= n {
		l.selected = n - 1
	}
}

func (l *listing) accept(ed *Editor) {
	if l.selected >= 0 {
		l.provider.Accept(l.selected, ed)
	}
}

func (l *listing) handleFilterKey(k ui.Key) bool {
	if likeChar(k) {
		l.changeFilter(l.filter + string(k.Rune))
		return true
	}
	return false
}

func (l *listing) defaultBinding(ed *Editor) {
	if !l.handleFilterKey(ed.lastKey) {
		insertStart(ed)
		ed.nextAction = action{typ: reprocessKey}
	}
}

func registerListingBuiltins(
	module string,
	impls map[string]func(*Editor), l func(*Editor) *listing) struct{} {

	impls["up"] = func(ed *Editor) { l(ed).up(false) }
	impls["up-cycle"] = func(ed *Editor) { l(ed).up(true) }
	impls["page-up"] = func(ed *Editor) { l(ed).pageUp() }
	impls["down"] = func(ed *Editor) { l(ed).down(false) }
	impls["down-cycle"] = func(ed *Editor) { l(ed).down(true) }
	impls["page-down"] = func(ed *Editor) { l(ed).pageDown() }
	impls["backspace"] = func(ed *Editor) { l(ed).backspace() }
	impls["accept"] = func(ed *Editor) { l(ed).accept(ed) }
	impls["accept-close"] = func(ed *Editor) { l(ed).accept(ed); insertStart(ed) }
	impls["default"] = func(ed *Editor) { l(ed).defaultBinding(ed) }
	return registerBuiltins(module, impls)
}

func registerListingBindings(
	mt ModeType, defaultMod string, m map[ui.Key]string) struct{} {

	m[ui.Key{ui.Up, 0}] = "up"
	m[ui.Key{ui.PageUp, 0}] = "page-up"
	m[ui.Key{ui.Down, 0}] = "down"
	m[ui.Key{ui.PageDown, 0}] = "page-down"
	m[ui.Key{ui.Tab, 0}] = "down-cycle"
	m[ui.Key{ui.Backspace, 0}] = "backspace"
	m[ui.Key{ui.Enter, 0}] = "accept-close"
	m[ui.Key{ui.Enter, ui.Alt}] = "accept"
	m[ui.Default] = "default"
	m[ui.Key{'[', ui.Ctrl}] = "insert:start"
	return registerBindings(mt, defaultMod, m)
}
<commit_msg>When adding listing-common bindings, don't overwrite what is already bound.<commit_after>package edit

import (
	"container/list"
	"fmt"
	"strings"
	"unicode/utf8"

	"github.com/elves/elvish/edit/ui"
	"github.com/elves/elvish/util"
)

// listing implements a listing mode that supports the notion of selecting an
// entry and filtering entries.
type listing struct {
	typ         ModeType
	provider    listingProvider
	selected    int
	filter      string
	pagesize    int
	headerWidth int
}

type listingProvider interface {
	Len() int
	Show(i int) (string, ui.Styled)
	Filter(filter string) int
	Accept(i int, ed *Editor)
	ModeTitle(int) string
}

type Placeholderer interface {
	Placeholder() string
}

func newListing(t ModeType, p listingProvider) listing {
	l := listing{t, p, 0, "", 0, 0}
	l.changeFilter("")
	for i := 0; i < p.Len(); i++ {
		header, _ := p.Show(i)
		width := util.Wcswidth(header)
		if l.headerWidth < width {
			l.headerWidth = width
		}
	}
	return l
}

func (l *listing) Mode() ModeType {
	return l.typ
}

func (l *listing) ModeLine() renderer {
	return modeLineRenderer{l.provider.ModeTitle(l.selected), l.filter}
}

func (l *listing) List(maxHeight int) renderer {
	n := l.provider.Len()
	if n == 0 {
		var ph string
		if pher, ok := l.provider.(Placeholderer); ok {
			ph = pher.Placeholder()
		} else {
			ph = "(no result)"
		}
		return placeholderRenderer(ph)
	}

	// Collect the entries to show. We start from the selected entry and extend
	// in both directions alternatingly. The entries are split into lines and
	// then collected in a list.
	low := l.selected
	if low == -1 {
		low = 0
	}
	high := low
	height := 0
	var listOfLines list.List
	getEntry := func(i int) []ui.Styled {
		header, content := l.provider.Show(i)
		lines := strings.Split(content.Text, "\n")
		styles := content.Styles
		if i == l.selected {
			styles = append(styles, styleForSelected...)
		}
		styleds := make([]ui.Styled, len(lines))
		for i, line := range lines {
			if l.headerWidth > 0 {
				if i == 0 {
					line = fmt.Sprintf("%*s %s", l.headerWidth, header, line)
				} else {
					line = fmt.Sprintf("%*s %s", l.headerWidth, "", line)
				}
			}
			styleds[i] = ui.Styled{line, styles}
		}
		return styleds
	}
	// We start by extending high, so that the first entry to include is
	// l.selected.
	extendLow := false
	lastShownIncomplete := false
	for height < maxHeight && !(low == 0 && high == n) {
		var i int
		if (extendLow && low > 0) || high == n {
			low--

			entry := getEntry(low)
			// Prepend at most the last (height - maxHeight) lines.
			for i = len(entry) - 1; i >= 0 && height < maxHeight; i-- {
				listOfLines.PushFront(entry[i])
				height++
			}
			if i >= 0 {
				lastShownIncomplete = true
			}
		} else {
			entry := getEntry(high)
			// Append at most the first (height - maxHeight) lines.
			for i = 0; i < len(entry) && height < maxHeight; i++ {
				listOfLines.PushBack(entry[i])
				height++
			}
			if i < len(entry) {
				lastShownIncomplete = true
			}

			high++
		}
		extendLow = !extendLow
	}

	l.pagesize = high - low

	// Convert the List to a slice.
	lines := make([]ui.Styled, 0, listOfLines.Len())
	for p := listOfLines.Front(); p != nil; p = p.Next() {
		lines = append(lines, p.Value.(ui.Styled))
	}

	ls := listingRenderer{lines}
	if low > 0 || high < n || lastShownIncomplete {
		// Need scrollbar
		return listingWithScrollBarRenderer{ls, n, low, high, height}
	}
	return ls
}

func writeHorizontalScrollbar(b *buffer, n, low, high, width int) {
	slow, shigh := findScrollInterval(n, low, high, width)
	for i := 0; i < width; i++ {
		if slow <= i && i < shigh {
			b.write(' ', styleForScrollBarThumb.String())
		} else {
			b.write('━', styleForScrollBarArea.String())
		}
	}
}

func renderScrollbar(n, low, high, height int) *buffer {
	slow, shigh := findScrollInterval(n, low, high, height)
	// Logger.Printf("low = %d, high = %d, n = %d, slow = %d, shigh = %d", low, high, n, slow, shigh)
	b := newBuffer(1)
	for i := 0; i < height; i++ {
		if i > 0 {
			b.newline()
		}
		if slow <= i && i < shigh {
			b.write(' ', styleForScrollBarThumb.String())
		} else {
			b.write('│', styleForScrollBarArea.String())
		}
	}
	return b
}

func findScrollInterval(n, low, high, height int) (int, int) {
	f := func(i int) int {
		return int(float64(i)/float64(n)*float64(height) + 0.5)
	}
	scrollLow, scrollHigh := f(low), f(high)
	if scrollLow == scrollHigh {
		if scrollHigh == high {
			scrollLow--
		} else {
			scrollHigh++
		}
	}
	return scrollLow, scrollHigh
}

func (l *listing) changeFilter(newfilter string) {
	l.filter = newfilter
	l.selected = l.provider.Filter(newfilter)
}

func (l *listing) backspace() bool {
	_, size := utf8.DecodeLastRuneInString(l.filter)
	if size > 0 {
		l.changeFilter(l.filter[:len(l.filter)-size])
		return true
	}
	return false
}

func (l *listing) up(cycle bool) {
	n := l.provider.Len()
	if n == 0 {
		return
	}
	l.selected--
	if l.selected == -1 {
		if cycle {
			l.selected += n
		} else {
			l.selected++
		}
	}
}

func (l *listing) pageUp() {
	n := l.provider.Len()
	if n == 0 {
		return
	}
	l.selected -= l.pagesize
	if l.selected < 0 {
		l.selected = 0
	}
}

func (l *listing) down(cycle bool) {
	n := l.provider.Len()
	if n == 0 {
		return
	}
	l.selected++
	if l.selected == n {
		if cycle {
			l.selected -= n
		} else {
			l.selected--
		}
	}
}

func (l *listing) pageDown() {
	n := l.provider.Len()
	if n == 0 {
		return
	}
	l.selected += l.pagesize
	if l.selected >= n {
		l.selected = n - 1
	}
}

func (l *listing) accept(ed *Editor) {
	if l.selected >= 0 {
		l.provider.Accept(l.selected, ed)
	}
}

func (l *listing) handleFilterKey(k ui.Key) bool {
	if likeChar(k) {
		l.changeFilter(l.filter + string(k.Rune))
		return true
	}
	return false
}

func (l *listing) defaultBinding(ed *Editor) {
	if !l.handleFilterKey(ed.lastKey) {
		insertStart(ed)
		ed.nextAction = action{typ: reprocessKey}
	}
}

func registerListingBuiltins(
	module string,
	impls map[string]func(*Editor), l func(*Editor) *listing) struct{} {

	impls["up"] = func(ed *Editor) { l(ed).up(false) }
	impls["up-cycle"] = func(ed *Editor) { l(ed).up(true) }
	impls["page-up"] = func(ed *Editor) { l(ed).pageUp() }
	impls["down"] = func(ed *Editor) { l(ed).down(false) }
	impls["down-cycle"] = func(ed *Editor) { l(ed).down(true) }
	impls["page-down"] = func(ed *Editor) { l(ed).pageDown() }
	impls["backspace"] = func(ed *Editor) { l(ed).backspace() }
	impls["accept"] = func(ed *Editor) { l(ed).accept(ed) }
	impls["accept-close"] = func(ed *Editor) { l(ed).accept(ed); insertStart(ed) }
	impls["default"] = func(ed *Editor) { l(ed).defaultBinding(ed) }
	return registerBuiltins(module, impls)
}

var defaultListingBindings = map[ui.Key]string{
	ui.Key{ui.Up, 0}:         "up",
	ui.Key{ui.PageUp, 0}:     "page-up",
	ui.Key{ui.Down, 0}:       "down",
	ui.Key{ui.PageDown, 0}:   "page-down",
	ui.Key{ui.Tab, 0}:        "down-cycle",
	ui.Key{ui.Backspace, 0}:  "backspace",
	ui.Key{ui.Enter, 0}:      "accept-close",
	ui.Key{ui.Enter, ui.Alt}: "accept",
	ui.Default:               "default",
	ui.Key{'[', ui.Ctrl}:     "insert:start",
}

func registerListingBindings(
	mt ModeType, defaultMod string, m map[ui.Key]string) struct{} {

	for k, defaultBinding := range defaultListingBindings {
		if _, alreadyBound := m[k]; !alreadyBound {
			m[k] = defaultBinding
		}
	}
	return registerBindings(mt, defaultMod, m)
}
<|endoftext|>


<commit_before>// Package rpc is a go-micro rpc handler.
package rpc

import (
	"encoding/json"
	"io"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"

	"github.com/joncalhoun/qson"
	"github.com/micro/go-micro/api"
	"github.com/micro/go-micro/api/handler"
	proto "github.com/micro/go-micro/api/internal/proto"
	"github.com/micro/go-micro/client"
	"github.com/micro/go-micro/client/selector"
	"github.com/micro/go-micro/codec"
	"github.com/micro/go-micro/codec/jsonrpc"
	"github.com/micro/go-micro/codec/protorpc"
	"github.com/micro/go-micro/errors"
	"github.com/micro/go-micro/registry"
	"github.com/micro/go-micro/util/ctx"
)

const (
	Handler = "rpc"
)

var (
	// supported json codecs
	jsonCodecs = []string{
		"application/grpc+json",
		"application/json",
		"application/json-rpc",
	}

	// support proto codecs
	protoCodecs = []string{
		"application/grpc",
		"application/grpc+proto",
		"application/proto",
		"application/protobuf",
		"application/proto-rpc",
		"application/octet-stream",
	}
)

type rpcHandler struct {
	opts handler.Options
	s    *api.Service
}

type buffer struct {
	io.ReadCloser
}

func (b *buffer) Write(_ []byte) (int, error) {
	return 0, nil
}

// strategy is a hack for selection
func strategy(services []*registry.Service) selector.Strategy {
	return func(_ []*registry.Service) selector.Next {
		// ignore input to this function, use services above
		return selector.Random(services)
	}
}

func (h *rpcHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()
	var service *api.Service

	if h.s != nil {
		// we were given the service
		service = h.s
	} else if h.opts.Router != nil {
		// try get service from router
		s, err := h.opts.Router.Route(r)
		if err != nil {
			writeError(w, r, errors.InternalServerError("go.micro.api", err.Error()))
			return
		}
		service = s
	} else {
		// we have no way of routing the request
		writeError(w, r, errors.InternalServerError("go.micro.api", "no route found"))
		return
	}

	// only allow post when we have the router
	if r.Method != "GET" && (h.opts.Router != nil && r.Method != "POST") {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	ct := r.Header.Get("Content-Type")

	// Strip charset from Content-Type (like `application/json; charset=UTF-8`)
	if idx := strings.IndexRune(ct, ';'); idx >= 0 {
		ct = ct[:idx]
	}

	// micro client
	c := h.opts.Service.Client()

	// create strategy
	so := selector.WithStrategy(strategy(service.Services))

	// get payload
	br, err := requestPayload(r)
	if err != nil {
		writeError(w, r, err)
		return
	}

	// create context
	cx := ctx.FromRequest(r)

	var rsp []byte

	switch {
	// json codecs
	case hasCodec(ct, jsonCodecs):
		var request json.RawMessage
		// if the extracted payload isn't empty lets use it
		if len(br) > 0 {
			request = json.RawMessage(br)
		}

		// create request/response
		var response json.RawMessage

		req := c.NewRequest(
			service.Name,
			service.Endpoint.Name,
			&request,
			client.WithContentType(ct),
		)

		// make the call
		if err := c.Call(cx, req, &response, client.WithSelectOption(so)); err != nil {
			writeError(w, r, err)
			return
		}

		// marshall response
		rsp, _ = response.MarshalJSON()
	// proto codecs
	case hasCodec(ct, protoCodecs):
		request := &proto.Message{}
		// if the extracted payload isn't empty lets use it
		if len(br) > 0 {
			request = proto.NewMessage(br)
		}

		// create request/response
		response := &proto.Message{}

		req := c.NewRequest(
			service.Name,
			service.Endpoint.Name,
			request,
			client.WithContentType(ct),
		)

		// make the call
		if err := c.Call(cx, req, response, client.WithSelectOption(so)); err != nil {
			writeError(w, r, err)
			return
		}

		// marshall response
		rsp, _ = response.Marshal()
	default:
		http.Error(w, "Unsupported Content-Type", 400)
		return
	}

	// write the response
	writeResponse(w, r, rsp)
}

func (rh *rpcHandler) String() string {
	return "rpc"
}

func hasCodec(ct string, codecs []string) bool {
	for _, codec := range codecs {
		if ct == codec {
			return true
		}
	}
	return false
}

// requestPayload takes a *http.Request.
// If the request is a GET the query string parameters are extracted and marshaled to JSON and the raw bytes are returned.
// If the request method is a POST the request body is read and returned
func requestPayload(r *http.Request) ([]byte, error) {
	// we have to decode json-rpc and proto-rpc because we suck
	// well actually because there's no proxy codec right now
	switch r.Header.Get("Content-Type") {
	case "application/json-rpc":
		msg := codec.Message{
			Type:   codec.Request,
			Header: make(map[string]string),
		}
		c := jsonrpc.NewCodec(&buffer{r.Body})
		if err := c.ReadHeader(&msg, codec.Request); err != nil {
			return nil, err
		}
		var raw json.RawMessage
		if err := c.ReadBody(&raw); err != nil {
			return nil, err
		}
		return ([]byte)(raw), nil
	case "application/proto-rpc", "application/octet-stream":
		msg := codec.Message{
			Type:   codec.Request,
			Header: make(map[string]string),
		}
		c := protorpc.NewCodec(&buffer{r.Body})
		if err := c.ReadHeader(&msg, codec.Request); err != nil {
			return nil, err
		}
		var raw proto.Message
		if err := c.ReadBody(&raw); err != nil {
			return nil, err
		}
		b, _ := raw.Marshal()
		return b, nil
	}

	// otherwise as per usual

	switch r.Method {
	case "GET":
		if len(r.URL.RawQuery) > 0 {
			return qson.ToJSON(r.URL.RawQuery)
		}
	case "PATCH", "POST":
		return ioutil.ReadAll(r.Body)
	}

	return []byte{}, nil
}

func writeError(w http.ResponseWriter, r *http.Request, err error) {
	ce := errors.Parse(err.Error())

	switch ce.Code {
	case 0:
		// assuming it's totally screwed
		ce.Code = 500
		ce.Id = "go.micro.api"
		ce.Status = http.StatusText(500)
		ce.Detail = "error during request: " + ce.Detail
		w.WriteHeader(500)
	default:
		w.WriteHeader(int(ce.Code))
	}

	// response content type
	w.Header().Set("Content-Type", "application/json")

	// Set trailers
	if strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
		w.Header().Set("Trailer", "grpc-status")
		w.Header().Set("Trailer", "grpc-message")
		w.Header().Set("grpc-status", "13")
		w.Header().Set("grpc-message", ce.Detail)
	}

	w.Write([]byte(ce.Error()))
}

func writeResponse(w http.ResponseWriter, r *http.Request, rsp []byte) {
	w.Header().Set("Content-Type", r.Header.Get("Content-Type"))
	w.Header().Set("Content-Length", strconv.Itoa(len(rsp)))

	// Set trailers
	if strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
		w.Header().Set("Trailer", "grpc-status")
		w.Header().Set("Trailer", "grpc-message")
		w.Header().Set("grpc-status", "0")
		w.Header().Set("grpc-message", "")
	}

	// write response
	w.Write(rsp)
}

func NewHandler(opts ...handler.Option) handler.Handler {
	options := handler.NewOptions(opts...)
	return &rpcHandler{
		opts: options,
	}
}

func WithService(s *api.Service, opts ...handler.Option) handler.Handler {
	options := handler.NewOptions(opts...)
	return &rpcHandler{
		opts: options,
		s:    s,
	}
}
<commit_msg>Default to json content-type in api<commit_after>// Package rpc is a go-micro rpc handler.
package rpc

import (
	"encoding/json"
	"io"
	"io/ioutil"
	"net/http"
	"strconv"
	"strings"

	"github.com/joncalhoun/qson"
	"github.com/micro/go-micro/api"
	"github.com/micro/go-micro/api/handler"
	proto "github.com/micro/go-micro/api/internal/proto"
	"github.com/micro/go-micro/client"
	"github.com/micro/go-micro/client/selector"
	"github.com/micro/go-micro/codec"
	"github.com/micro/go-micro/codec/jsonrpc"
	"github.com/micro/go-micro/codec/protorpc"
	"github.com/micro/go-micro/errors"
	"github.com/micro/go-micro/registry"
	"github.com/micro/go-micro/util/ctx"
)

const (
	Handler = "rpc"
)

var (
	// supported json codecs
	jsonCodecs = []string{
		"application/grpc+json",
		"application/json",
		"application/json-rpc",
	}

	// support proto codecs
	protoCodecs = []string{
		"application/grpc",
		"application/grpc+proto",
		"application/proto",
		"application/protobuf",
		"application/proto-rpc",
		"application/octet-stream",
	}
)

type rpcHandler struct {
	opts handler.Options
	s    *api.Service
}

type buffer struct {
	io.ReadCloser
}

func (b *buffer) Write(_ []byte) (int, error) {
	return 0, nil
}

// strategy is a hack for selection
func strategy(services []*registry.Service) selector.Strategy {
	return func(_ []*registry.Service) selector.Next {
		// ignore input to this function, use services above
		return selector.Random(services)
	}
}

func (h *rpcHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()
	var service *api.Service

	if h.s != nil {
		// we were given the service
		service = h.s
	} else if h.opts.Router != nil {
		// try get service from router
		s, err := h.opts.Router.Route(r)
		if err != nil {
			writeError(w, r, errors.InternalServerError("go.micro.api", err.Error()))
			return
		}
		service = s
	} else {
		// we have no way of routing the request
		writeError(w, r, errors.InternalServerError("go.micro.api", "no route found"))
		return
	}

	// only allow post when we have the router
	if r.Method != "GET" && (h.opts.Router != nil && r.Method != "POST") {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	ct := r.Header.Get("Content-Type")

	// Strip charset from Content-Type (like `application/json; charset=UTF-8`)
	if idx := strings.IndexRune(ct, ';'); idx >= 0 {
		ct = ct[:idx]
	}

	// micro client
	c := h.opts.Service.Client()

	// create strategy
	so := selector.WithStrategy(strategy(service.Services))

	// get payload
	br, err := requestPayload(r)
	if err != nil {
		writeError(w, r, err)
		return
	}

	// create context
	cx := ctx.FromRequest(r)

	var rsp []byte

	switch {
	// proto codecs
	case hasCodec(ct, protoCodecs):
		request := &proto.Message{}
		// if the extracted payload isn't empty lets use it
		if len(br) > 0 {
			request = proto.NewMessage(br)
		}

		// create request/response
		response := &proto.Message{}

		req := c.NewRequest(
			service.Name,
			service.Endpoint.Name,
			request,
			client.WithContentType(ct),
		)

		// make the call
		if err := c.Call(cx, req, response, client.WithSelectOption(so)); err != nil {
			writeError(w, r, err)
			return
		}

		// marshall response
		rsp, _ = response.Marshal()
	default:
		// if json codec is not present set to json
		if !hasCodec(ct, jsonCodecs) {
			ct = "application/json"
		}

		// default to trying json
		var request json.RawMessage
		// if the extracted payload isn't empty lets use it
		if len(br) > 0 {
			request = json.RawMessage(br)
		}

		// create request/response
		var response json.RawMessage

		req := c.NewRequest(
			service.Name,
			service.Endpoint.Name,
			&request,
			client.WithContentType(ct),
		)

		// make the call
		if err := c.Call(cx, req, &response, client.WithSelectOption(so)); err != nil {
			writeError(w, r, err)
			return
		}

		// marshall response
		rsp, _ = response.MarshalJSON()
	}

	// write the response
	writeResponse(w, r, rsp)
}

func (rh *rpcHandler) String() string {
	return "rpc"
}

func hasCodec(ct string, codecs []string) bool {
	for _, codec := range codecs {
		if ct == codec {
			return true
		}
	}
	return false
}

// requestPayload takes a *http.Request.
// If the request is a GET the query string parameters are extracted and marshaled to JSON and the raw bytes are returned.
// If the request method is a POST the request body is read and returned
func requestPayload(r *http.Request) ([]byte, error) {
	// we have to decode json-rpc and proto-rpc because we suck
	// well actually because there's no proxy codec right now
	switch r.Header.Get("Content-Type") {
	case "application/json-rpc":
		msg := codec.Message{
			Type:   codec.Request,
			Header: make(map[string]string),
		}
		c := jsonrpc.NewCodec(&buffer{r.Body})
		if err := c.ReadHeader(&msg, codec.Request); err != nil {
			return nil, err
		}
		var raw json.RawMessage
		if err := c.ReadBody(&raw); err != nil {
			return nil, err
		}
		return ([]byte)(raw), nil
	case "application/proto-rpc", "application/octet-stream":
		msg := codec.Message{
			Type:   codec.Request,
			Header: make(map[string]string),
		}
		c := protorpc.NewCodec(&buffer{r.Body})
		if err := c.ReadHeader(&msg, codec.Request); err != nil {
			return nil, err
		}
		var raw proto.Message
		if err := c.ReadBody(&raw); err != nil {
			return nil, err
		}
		b, _ := raw.Marshal()
		return b, nil
	}

	// otherwise as per usual

	switch r.Method {
	case "GET":
		if len(r.URL.RawQuery) > 0 {
			return qson.ToJSON(r.URL.RawQuery)
		}
	case "PATCH", "POST":
		return ioutil.ReadAll(r.Body)
	}

	return []byte{}, nil
}

func writeError(w http.ResponseWriter, r *http.Request, err error) {
	ce := errors.Parse(err.Error())

	switch ce.Code {
	case 0:
		// assuming it's totally screwed
		ce.Code = 500
		ce.Id = "go.micro.api"
		ce.Status = http.StatusText(500)
		ce.Detail = "error during request: " + ce.Detail
		w.WriteHeader(500)
	default:
		w.WriteHeader(int(ce.Code))
	}

	// response content type
	w.Header().Set("Content-Type", "application/json")

	// Set trailers
	if strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
		w.Header().Set("Trailer", "grpc-status")
		w.Header().Set("Trailer", "grpc-message")
		w.Header().Set("grpc-status", "13")
		w.Header().Set("grpc-message", ce.Detail)
	}

	w.Write([]byte(ce.Error()))
}

func writeResponse(w http.ResponseWriter, r *http.Request, rsp []byte) {
	w.Header().Set("Content-Type", r.Header.Get("Content-Type"))
	w.Header().Set("Content-Length", strconv.Itoa(len(rsp)))

	// Set trailers
	if strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
		w.Header().Set("Trailer", "grpc-status")
		w.Header().Set("Trailer", "grpc-message")
		w.Header().Set("grpc-status", "0")
		w.Header().Set("grpc-message", "")
	}

	// write response
	w.Write(rsp)
}

func NewHandler(opts ...handler.Option) handler.Handler {
	options := handler.NewOptions(opts...)
	return &rpcHandler{
		opts: options,
	}
}

func WithService(s *api.Service, opts ...handler.Option) handler.Handler {
	options := handler.NewOptions(opts...)
	return &rpcHandler{
		opts: options,
		s:    s,
	}
}
<|endoftext|>


<commit_before>package tddbc

import (
	"testing"
)

func Test正常_インスタンスが作成できる(t *testing.T) {
	target := NewClosedRange(3, 8)
	if target == nil {
		t.Error("instance is nil")
	}
}

func Test正常_閉区間3to8を作成し下端点が取得できることを確認する(t *testing.T) {
	expected := 3
	target := NewClosedRange(3, 8)
	if target.lower != expected {
		t.Errorf("failed get lower expected=%d, actual=%d\n", expected, target.lower)
	}
}

func Test正常_閉区間3to8を作成し上端点が取得できることを確認する(t *testing.T) {
	expected := 8
	target := NewClosedRange(3, 8)
	if target.upper != expected {
		t.Errorf("failed get lower expected=%d, actual=%d\n", expected, target.upper)
	}
}
<commit_msg>下端点を変更しても正しく取得できるか確認するテストケースに変更<commit_after>package tddbc

import (
	"testing"
)

func Test正常_インスタンスが作成できる(t *testing.T) {
	target := NewClosedRange(3, 8)
	if target == nil {
		t.Error("instance is nil")
	}
}

func Test正常_閉区間を作成し下端点が取得できることを確認する(t *testing.T) {
	var data = []struct {
		lower    int
		upper    int
		expected int
	}{
		{1, 8, 1},
		{2, 8, 2},
		{3, 8, 3},
		{4, 8, 4},
	}

	for _, d := range data {
		expected := d.expected
		target := NewClosedRange(d.lower, d.upper)
		if target.lower != expected {
			t.Errorf("failed get lower expected=%d, actual=%d\n", expected, target.lower)
		}
	}
}

func Test正常_閉区間3to8を作成し上端点が取得できることを確認する(t *testing.T) {
	expected := 8
	target := NewClosedRange(3, 8)
	if target.upper != expected {
		t.Errorf("failed get lower expected=%d, actual=%d\n", expected, target.upper)
	}
}
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.552"
<commit_msg>fnserver: 0.3.553 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.553"
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.72"
<commit_msg>functions: 0.3.73 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.73"
<|endoftext|>


<commit_before>/*
Package cyclonedx is responsible for generating a CycloneDX XML report for the given container image or file system.
*/
package cyclonedx

import (
	"encoding/xml"
	"fmt"
	"io"

	"github.com/anchore/syft/syft/distro"

	"github.com/anchore/syft/syft/pkg"
	"github.com/anchore/syft/syft/scope"
)

// Presenter writes a CycloneDX report from the given Catalog and Scope contents
type Presenter struct {
	catalog *pkg.Catalog
	scope   scope.Scope
	distro  distro.Distro
}

// NewPresenter creates a CycloneDX presenter from the given Catalog and Scope objects.
func NewPresenter(catalog *pkg.Catalog, s scope.Scope, d distro.Distro) *Presenter {
	return &Presenter{
		catalog: catalog,
		scope:   s,
		distro:  d,
	}
}

// Present writes the CycloneDX report to the given io.Writer.
func (pres *Presenter) Present(output io.Writer) error {
	bom := NewDocumentFromCatalog(pres.catalog, pres.distro)

	srcObj := pres.scope.Source()

	switch src := srcObj.(type) {
	case scope.DirSource:
		bom.BomDescriptor.Component = &BdComponent{
			Component: Component{
				Type:    "file",
				Name:    src.Path,
				Version: "",
			},
		}
	case scope.ImageSource:
		var imageID string
		var versionStr string
		if len(src.Img.Metadata.Tags) > 0 {
			imageID = src.Img.Metadata.Tags[0].Context().Name()
			versionStr = src.Img.Metadata.Tags[0].TagStr()
		} else {
			imageID = src.Img.Metadata.Digest
		}
		src.Img.Metadata.Tags[0].TagStr()
		bom.BomDescriptor.Component = &BdComponent{
			Component: Component{
				Type:    "container",
				Name:    imageID,
				Version: versionStr,
			},
		}
	default:
		return fmt.Errorf("unsupported source: %T", src)
	}

	encoder := xml.NewEncoder(output)
	encoder.Indent("", "  ")

	_, err := output.Write([]byte(xml.Header))
	if err != nil {
		return err
	}

	err = encoder.Encode(bom)
	if err != nil {
		return err
	}

	_, err = output.Write([]byte("\n"))
	return err
}
<commit_msg>remove accessing tag when not available (#174)<commit_after>/*
Package cyclonedx is responsible for generating a CycloneDX XML report for the given container image or file system.
*/
package cyclonedx

import (
	"encoding/xml"
	"fmt"
	"io"

	"github.com/anchore/syft/syft/distro"

	"github.com/anchore/syft/syft/pkg"
	"github.com/anchore/syft/syft/scope"
)

// Presenter writes a CycloneDX report from the given Catalog and Scope contents
type Presenter struct {
	catalog *pkg.Catalog
	scope   scope.Scope
	distro  distro.Distro
}

// NewPresenter creates a CycloneDX presenter from the given Catalog and Scope objects.
func NewPresenter(catalog *pkg.Catalog, s scope.Scope, d distro.Distro) *Presenter {
	return &Presenter{
		catalog: catalog,
		scope:   s,
		distro:  d,
	}
}

// Present writes the CycloneDX report to the given io.Writer.
func (pres *Presenter) Present(output io.Writer) error {
	bom := NewDocumentFromCatalog(pres.catalog, pres.distro)

	srcObj := pres.scope.Source()

	switch src := srcObj.(type) {
	case scope.DirSource:
		bom.BomDescriptor.Component = &BdComponent{
			Component: Component{
				Type:    "file",
				Name:    src.Path,
				Version: "",
			},
		}
	case scope.ImageSource:
		var imageID string
		var versionStr string
		if len(src.Img.Metadata.Tags) > 0 {
			imageID = src.Img.Metadata.Tags[0].Context().Name()
			versionStr = src.Img.Metadata.Tags[0].TagStr()
		} else {
			imageID = src.Img.Metadata.Digest
		}
		bom.BomDescriptor.Component = &BdComponent{
			Component: Component{
				Type:    "container",
				Name:    imageID,
				Version: versionStr,
			},
		}
	default:
		return fmt.Errorf("unsupported source: %T", src)
	}

	encoder := xml.NewEncoder(output)
	encoder.Indent("", "  ")

	_, err := output.Write([]byte(xml.Header))
	if err != nil {
		return err
	}

	err = encoder.Encode(bom)
	if err != nil {
		return err
	}

	_, err = output.Write([]byte("\n"))
	return err
}
<|endoftext|>


<commit_before>// Copyright 2016 IBM Corporation
//
//   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 main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"
)

const (
	userCookie          = "user"
	requestIDHeader     = "X-Request-ID"
	enableRatingsEnvVar = "ENABLE_RATINGS"
	starColorEnvVar     = "STAR_COLOR"
	defaultStarColor    = "black"
)

// Globals
var (
	proxyURL      string
	enableRatings bool
	starColor     string
)

type review struct {
	Text   string  `json:"text,omitempty"`
	Rating *rating `json:"rating,omitempty"`
}

type rating struct {
	Stars int    `json:"stars,omitempty"`
	Color string `json:"color,omitempty"`
}

var reviews = map[string]*review{
	"reviewer1": {
		Text: "An extremely entertaining play by Shakespeare. The slapstick humour is refreshing!",
	},
	"reviewer2": {
		Text: "Absolutely fun and entertaining. The play lacks thematic depth when compared to other plays by Shakespeare.",
	},
}

func main() {
	if len(os.Args) < 3 {
		log.Printf("Usage: %s <port> <proxy url>", os.Args[0])
		os.Exit(-1)
	}

	port := os.Args[1]
	proxyURL = os.Args[2]

	enableRatings = os.Getenv(enableRatingsEnvVar) == "true"
	starColor = os.Getenv(starColorEnvVar)
	if starColor == "" {
		starColor = defaultStarColor
	}

	http.HandleFunc("/reviews", reviewsHandler)
	http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
	})
	log.Fatal(http.ListenAndServe(":"+port, nil))
}

func reviewsHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	var ratings map[string]*rating
	if enableRatings {
		ratings = getRatings(getForwardHeaders(r))
	} else {
		ratings = map[string]*rating{}
	}

	ratedReviews := make(map[string]*review, len(reviews))
	for k, v := range reviews {
		ratedReviews[k] = &review{
			Text:   v.Text,
			Rating: ratings[k],
		}
	}

	bytes, _ := json.Marshal(ratedReviews)
	w.Write(bytes)
}

func getRatings(forwardHeaders http.Header) map[string]*rating {
	timeout := 2500 * time.Millisecond
	if starColor == defaultStarColor {
		timeout = 10 * time.Second
	}

	ratings := map[string]*rating{}

	bytes, err := doRequest("/ratings/ratings", forwardHeaders, timeout)
	if err != nil {
		log.Printf("Error getting ratings: %v", err)
		return ratings
	}
	json.Unmarshal(bytes, &ratings)

	for _, v := range ratings {
		v.Color = starColor
	}

	return ratings
}

func doRequest(path string, forwardHeaders http.Header, timeout time.Duration) ([]byte, error) {
	client := http.Client{}
	client.Timeout = timeout

	req, _ := http.NewRequest("GET", proxyURL+path, nil)
	req.Header = forwardHeaders

	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("received unexpected status code %d", resp.StatusCode)
	}

	return ioutil.ReadAll(resp.Body)
}

func getForwardHeaders(r *http.Request) http.Header {
	fwdReq, _ := http.NewRequest("GET", "dummy", nil)

	cookie, err := r.Cookie(userCookie)
	if err != http.ErrNoCookie {
		fwdReq.AddCookie(cookie)
	}

	reqID := r.Header.Get(requestIDHeader)
	if reqID != "" {
		fwdReq.Header.Set(requestIDHeader, reqID)
	}

	return fwdReq.Header
}
<commit_msg>Added a debug API to the reviews service<commit_after>// Copyright 2016 IBM Corporation
//
//   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 main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"
)

const (
	userCookie          = "user"
	requestIDHeader     = "X-Request-ID"
	enableRatingsEnvVar = "ENABLE_RATINGS"
	starColorEnvVar     = "STAR_COLOR"
	defaultStarColor    = "black"
)

// Globals
var (
	proxyURL      string
	enableRatings bool
	starColor     string
)

type review struct {
	Text   string  `json:"text,omitempty"`
	Rating *rating `json:"rating,omitempty"`
}

type rating struct {
	Stars int    `json:"stars,omitempty"`
	Color string `json:"color,omitempty"`
}

var reviews = map[string]*review{
	"reviewer1": {
		Text: "An extremely entertaining play by Shakespeare. The slapstick humour is refreshing!",
	},
	"reviewer2": {
		Text: "Absolutely fun and entertaining. The play lacks thematic depth when compared to other plays by Shakespeare.",
	},
}

func main() {
	if len(os.Args) < 3 {
		log.Printf("Usage: %s <port> <proxy url>", os.Args[0])
		os.Exit(-1)
	}

	port := os.Args[1]
	proxyURL = os.Args[2]

	enableRatings = os.Getenv(enableRatingsEnvVar) == "true"
	starColor = os.Getenv(starColorEnvVar)
	if starColor == "" {
		starColor = defaultStarColor
	}

	http.HandleFunc("/reviews", reviewsHandler)
	http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
		conf := struct {
			EnableRatings bool
			StarColor     string
		}{
			EnableRatings: enableRatings,
			StarColor:     starColor,
		}

		data, _ := json.Marshal(&conf)
		w.Write(data)
		w.WriteHeader(http.StatusOK)
	})
	log.Fatal(http.ListenAndServe(":"+port, nil))
}

func reviewsHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	var ratings map[string]*rating
	if enableRatings {
		ratings = getRatings(getForwardHeaders(r))
	} else {
		ratings = map[string]*rating{}
	}

	ratedReviews := make(map[string]*review, len(reviews))
	for k, v := range reviews {
		ratedReviews[k] = &review{
			Text:   v.Text,
			Rating: ratings[k],
		}
	}

	bytes, _ := json.Marshal(ratedReviews)
	w.Write(bytes)
}

func getRatings(forwardHeaders http.Header) map[string]*rating {
	timeout := 2500 * time.Millisecond
	if starColor == defaultStarColor {
		timeout = 10 * time.Second
	}

	ratings := map[string]*rating{}

	bytes, err := doRequest("/ratings/ratings", forwardHeaders, timeout)
	if err != nil {
		log.Printf("Error getting ratings: %v", err)
		return ratings
	}
	json.Unmarshal(bytes, &ratings)

	for _, v := range ratings {
		v.Color = starColor
	}

	return ratings
}

func doRequest(path string, forwardHeaders http.Header, timeout time.Duration) ([]byte, error) {
	client := http.Client{}
	client.Timeout = timeout

	req, _ := http.NewRequest("GET", proxyURL+path, nil)
	req.Header = forwardHeaders

	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("received unexpected status code %d", resp.StatusCode)
	}

	return ioutil.ReadAll(resp.Body)
}

func getForwardHeaders(r *http.Request) http.Header {
	fwdReq, _ := http.NewRequest("GET", "dummy", nil)

	cookie, err := r.Cookie(userCookie)
	if err != http.ErrNoCookie {
		fwdReq.AddCookie(cookie)
	}

	reqID := r.Header.Get(requestIDHeader)
	if reqID != "" {
		fwdReq.Header.Set(requestIDHeader, reqID)
	}

	return fwdReq.Header
}
<|endoftext|>


<commit_before>package controllers

import (
	"net/http"
	"os"

	"github.com/kayac/alphawing/app/models"

	"github.com/revel/revel"
)

type JsonResponse struct {
	Status  int      `json:"status"`
	Message []string `json:"message"`
}

type JsonResponseUploadBundle struct {
	*JsonResponse
	Content *models.BundleJsonResponse `json:"content"`
}

type ApiController struct {
	AlphaWingController
}

func (c ApiController) NewJsonResponse(stat int, mes []string) *JsonResponse {
	return &JsonResponse{
		Status:  stat,
		Message: mes,
	}
}

func (c ApiController) NewJsonResponseUploadBundle(stat int, mes []string, content *models.BundleJsonResponse) *JsonResponseUploadBundle {
	return &JsonResponseUploadBundle{
		c.NewJsonResponse(stat, mes),
		content,
	}
}

func (c ApiController) GetDocument() revel.Result {
	return c.Render()
}

func (c ApiController) PostUploadBundle(token string, description string, file *os.File) revel.Result {
	app, err := models.GetAppByApiToken(c.Txn, token)
	if err != nil {
		c.Response.Status = http.StatusUnauthorized
		return c.RenderJson(c.NewJsonResponseUploadBundle(c.Response.Status, []string{"Token is invalid."}, nil))
	}

	c.Validation.Required(file != nil).Message("File is required.")
	if c.Validation.HasErrors() {
		var errors []string
		for _, err := range c.Validation.Errors {
			errors = append(errors, err.String())
		}
		c.Response.Status = http.StatusBadRequest
		return c.RenderJson(c.NewJsonResponseUploadBundle(c.Response.Status, errors, nil))
	}

	bundle := &models.Bundle{
		Description: description,
		File:        file,
	}

	if err := app.CreateBundle(c.Txn, c.GoogleService, Conf.AaptPath, bundle); err != nil {
		if aperr, ok := err.(*models.ApkParseError); ok {
			c.Response.Status = http.StatusInternalServerError
			return c.RenderJson(c.NewJsonResponseUploadBundle(c.Response.Status, []string{aperr.Error()}, nil))
		}
		c.Response.Status = http.StatusInternalServerError
		return c.RenderJson(c.NewJsonResponseUploadBundle(c.Response.Status, []string{err.Error()}, nil))
	}

	content, err := bundle.JsonResponse(&c)
	if err != nil {
		c.Response.Status = http.StatusInternalServerError
		return c.RenderJson(c.NewJsonResponseUploadBundle(c.Response.Status, []string{err.Error()}, nil))
	}

	c.Response.Status = http.StatusOK
	return c.RenderJson(c.NewJsonResponseUploadBundle(c.Response.Status, []string{"Bundle is created!"}, content))
}
<commit_msg>do not use c.Txn in api.go<commit_after>package controllers

import (
	"net/http"
	"os"

	"github.com/kayac/alphawing/app/models"

	"github.com/coopernurse/gorp"
	"github.com/revel/revel"
)

type JsonResponse struct {
	Status  int      `json:"status"`
	Message []string `json:"message"`
}

type JsonResponseUploadBundle struct {
	*JsonResponse
	Content *models.BundleJsonResponse `json:"content"`
}

type ApiController struct {
	AlphaWingController
}

func (c ApiController) NewJsonResponse(stat int, mes []string) *JsonResponse {
	return &JsonResponse{
		Status:  stat,
		Message: mes,
	}
}

func (c ApiController) NewJsonResponseUploadBundle(stat int, mes []string, content *models.BundleJsonResponse) *JsonResponseUploadBundle {
	return &JsonResponseUploadBundle{
		c.NewJsonResponse(stat, mes),
		content,
	}
}

func (c ApiController) GetDocument() revel.Result {
	return c.Render()
}

func (c ApiController) PostUploadBundle(token string, description string, file *os.File) revel.Result {
	app, err := models.GetAppByApiToken(Dbm, token)
	if err != nil {
		c.Response.Status = http.StatusUnauthorized
		return c.RenderJson(c.NewJsonResponseUploadBundle(c.Response.Status, []string{"Token is invalid."}, nil))
	}

	c.Validation.Required(file != nil).Message("File is required.")
	if c.Validation.HasErrors() {
		var errors []string
		for _, err := range c.Validation.Errors {
			errors = append(errors, err.String())
		}
		c.Response.Status = http.StatusBadRequest
		return c.RenderJson(c.NewJsonResponseUploadBundle(c.Response.Status, errors, nil))
	}

	bundle := &models.Bundle{
		Description: description,
		File:        file,
	}

	err = Transact(func(txn gorp.SqlExecutor) error {
		return app.CreateBundle(txn, c.GoogleService, Conf.AaptPath, bundle)
	})
	if err != nil {
		if aperr, ok := err.(*models.ApkParseError); ok {
			c.Response.Status = http.StatusInternalServerError
			return c.RenderJson(c.NewJsonResponseUploadBundle(c.Response.Status, []string{aperr.Error()}, nil))
		}
		c.Response.Status = http.StatusInternalServerError
		return c.RenderJson(c.NewJsonResponseUploadBundle(c.Response.Status, []string{err.Error()}, nil))
	}

	content, err := bundle.JsonResponse(&c)
	if err != nil {
		c.Response.Status = http.StatusInternalServerError
		return c.RenderJson(c.NewJsonResponseUploadBundle(c.Response.Status, []string{err.Error()}, nil))
	}

	c.Response.Status = http.StatusOK
	return c.RenderJson(c.NewJsonResponseUploadBundle(c.Response.Status, []string{"Bundle is created!"}, content))
}
<|endoftext|>


<commit_before>package controllers

import (
	"database/sql"
	"errors"
	"os"
	"strconv"

	"github.com/kayac/alphawing/app/models"
	"github.com/kayac/alphawing/app/routes"

	"github.com/revel/revel"
)

type AppController struct {
	AuthController
	App *models.App
}

// not found, permission check
type AppControllerWithValidation struct {
	AppController
}

// ------------------------------------------------------
// AppController
func (c AppController) GetCreateApp() revel.Result {
	app := &models.App{}
	return c.Render(app)
}

func (c AppController) PostCreateApp(app models.App) revel.Result {
	c.Validation.Required(app.Title).Message("Title is required.")
	if c.Validation.HasErrors() {
		c.Validation.Keep()
		c.FlashParams()
		return c.Redirect(routes.AppController.GetCreateApp())
	}

	if err := models.CreateApp(c.Txn, c.GoogleService, &app); err != nil {
		panic(err)
	}

	tokeninfo, err := c.tokenInfo()
	if err != nil {
		panic(err)
	}
	authority := &models.Authority{
		Email: tokeninfo.Email,
	}
	if err := app.CreateAuthority(c.Txn, c.GoogleService, authority); err != nil {
		panic(err)
	}

	if err = c.createAudit(models.ResourceApp, app.Id, models.ActionCreate); err != nil {
		panic(err)
	}

	c.Flash.Success("Created!")
	return c.Redirect(routes.AppControllerWithValidation.GetApp(app.Id))
}

// ------------------------------------------------------
// AppControllerWithValidation
func (c AppControllerWithValidation) GetApp(appId int) revel.Result {
	app := c.App

	authorities, err := app.Authorities(c.Txn)
	if err != nil {
		panic(err)
	}

	bundles, err := app.Bundles(c.Txn)
	if err != nil {
		panic(err)
	}

	return c.Render(app, authorities, bundles)
}

func (c AppControllerWithValidation) GetUpdateApp(appId int) revel.Result {
	app := c.App
	return c.Render(app)
}

func (c AppControllerWithValidation) PostUpdateApp(appId int, app models.App) revel.Result {
	if appId != app.Id {
		c.Flash.Error("Parameter is invalid.")
		c.Redirect(routes.AppControllerWithValidation.GetUpdateApp(app.Id))
	}

	c.Validation.Required(app.Title).Message("Title is required.")
	if c.Validation.HasErrors() {
		c.Validation.Keep()
		c.FlashParams()
		return c.Redirect(routes.AppControllerWithValidation.GetUpdateApp(app.Id))
	}

	if err := app.Update(c.Txn); err != nil {
		panic(err)
	}

	if err := c.GoogleService.UpdateFileTitle(c.App.FileId, app.Title); err != nil {
		panic(err)
	}

	c.Flash.Success("Updated!")
	return c.Redirect(routes.AppControllerWithValidation.GetApp(app.Id))
}

func (c AppControllerWithValidation) PostRefreshToken(appId int, app models.App) revel.Result {
	if appId != app.Id {
		c.Flash.Error("Parameter is invalid")
		c.Redirect(routes.AppControllerWithValidation.GetApp(app.Id))
	}

	if err := app.RefreshToken(c.Txn); err != nil {
		panic(err)
	}

	c.Flash.Success("Refreshed!")
	return c.Redirect(routes.AppControllerWithValidation.GetApp(app.Id))
}

func (c AppControllerWithValidation) PostDeleteApp(appId int) revel.Result {
	app := c.App

	app.Delete(c.Txn, c.GoogleService)

	if err := c.createAudit(models.ResourceApp, appId, models.ActionDelete); err != nil {
		panic(err)
	}

	c.Flash.Success("Deleted!")
	return c.Redirect(routes.AlphaWingController.Index())
}

func (c AppControllerWithValidation) GetCreateBundle(appId int) revel.Result {
	app := c.App
	bundle := &models.Bundle{AppId: appId}
	return c.Render(app, bundle)
}

func (c AppControllerWithValidation) PostCreateBundle(appId int, bundle models.Bundle, file *os.File) revel.Result {
	if appId != bundle.AppId {
		c.Flash.Error("Parameter is invalid.")
		c.Redirect(routes.AppControllerWithValidation.GetApp(appId))
	}

	c.Validation.Required(file != nil).Message("File is required.")
	if c.Validation.HasErrors() {
		c.Validation.Keep()
		c.FlashParams()
		return c.Redirect(routes.AppControllerWithValidation.GetCreateBundle(appId))
	}

	bundle.File = file
	if _, ok := c.Params.Files["file"]; ok {
		bundle.FileName = c.Params.Files["file"][0].Filename
	}

	if err := c.App.CreateBundle(c.Txn, c.GoogleService, Conf.AaptPath, &bundle); err != nil {
		if aperr, ok := err.(*models.ApkParseError); ok {
			c.Flash.Error(aperr.Error())
			return c.Redirect(routes.AppControllerWithValidation.GetCreateBundle(appId))
		}
		panic(err)
	}

	if err := c.createAudit(models.ResourceBundle, bundle.Id, models.ActionCreate); err != nil {
		panic(err)
	}

	c.Flash.Success("Created!")
	return c.Redirect(routes.BundleControllerWithValidation.GetBundle(bundle.Id))
}

func (c AppControllerWithValidation) PostCreateAuthority(appId int, email string) revel.Result {
	app := c.App

	c.Validation.Required(email).Message("Email is required.")
	c.Validation.Email(email).Message("Email is invalid.")
	if c.Validation.HasErrors() {
		c.Validation.Keep()
		c.FlashParams()
		return c.Redirect(routes.AppControllerWithValidation.GetApp(appId))
	}

	found, err := app.HasAuthorityForEmail(c.Txn, email)
	if err != nil {
		panic(err)
	}
	c.Validation.Required(!found).Message(email + " is already registered.")
	if c.Validation.HasErrors() {
		c.Validation.Keep()
		c.FlashParams()
		return c.Redirect(routes.AppControllerWithValidation.GetApp(appId))
	}

	authority := &models.Authority{
		Email: email,
	}
	app.CreateAuthority(c.Txn, c.GoogleService, authority)

	if err := c.createAudit(models.ResourceAuthority, authority.Id, models.ActionCreate); err != nil {
		panic(err)
	}

	c.Flash.Success("Registered!")
	return c.Redirect(routes.AppControllerWithValidation.GetApp(appId))
}

func (c AppControllerWithValidation) PostDeleteAuthority(appId, authorityId int) revel.Result {
	app := c.App

	authority, err := models.GetAuthority(c.Txn, authorityId)
	if err != nil {
		panic(err)
	}

	if appId != authority.AppId {
		c.Flash.Error("Parameter is invalid.")
		return c.Redirect(routes.AppControllerWithValidation.GetApp(appId))
	}

	if err := app.DeleteAuthority(c.Txn, c.GoogleService, authority); err != nil {
		panic(err)
	}

	if err := c.createAudit(models.ResourceAuthority, authority.Id, models.ActionDelete); err != nil {
		panic(err)
	}

	c.Flash.Success("Deleted!")
	return c.Redirect(routes.AppControllerWithValidation.GetApp(appId))
}

func (c *AppControllerWithValidation) CheckNotFound() revel.Result {
	param := c.Params.Route["appId"]
	if len(param) == 0 {
		panic(errors.New("AppId is Required."))
	}
	appId, err := strconv.Atoi(param[0])
	if err != nil {
		panic(err)
	}
	app, err := models.GetApp(c.Txn, appId)
	if err != nil {
		if err == sql.ErrNoRows {
			return c.NotFound("NotFound")
		}
		panic(err)
	}
	c.App = app
	return nil
}

func (c *AppControllerWithValidation) CheckForbidden() revel.Result {
	if c.App == nil {
		c.NotFound("NotFound")
	}
	app := c.App
	s, err := c.userGoogleService()
	if err != nil {
		panic(err)
	}
	_, err = s.GetFile(app.FileId)
	if err != nil {
		return c.Forbidden("Forbidden")
	}
	return nil
}
<commit_msg>do not use c.Txn in app.go<commit_after>package controllers

import (
	"database/sql"
	"errors"
	"os"
	"strconv"

	"github.com/kayac/alphawing/app/models"
	"github.com/kayac/alphawing/app/routes"

	"github.com/coopernurse/gorp"
	"github.com/revel/revel"
)

type AppController struct {
	AuthController
	App *models.App
}

// not found, permission check
type AppControllerWithValidation struct {
	AppController
}

// ------------------------------------------------------
// AppController
func (c AppController) GetCreateApp() revel.Result {
	app := &models.App{}
	return c.Render(app)
}

func (c AppController) PostCreateApp(app models.App) revel.Result {
	c.Validation.Required(app.Title).Message("Title is required.")
	if c.Validation.HasErrors() {
		c.Validation.Keep()
		c.FlashParams()
		return c.Redirect(routes.AppController.GetCreateApp())
	}

	err := Transact(func(txn gorp.SqlExecutor) error {
		if err := models.CreateApp(txn, c.GoogleService, &app); err != nil {
			return err
		}

		tokeninfo, err := c.tokenInfo()
		if err != nil {
			return err
		}
		authority := &models.Authority{
			Email: tokeninfo.Email,
		}
		return app.CreateAuthority(txn, c.GoogleService, authority)
	})
	if err != nil {
		panic(err)
	}

	if err = c.createAudit(models.ResourceApp, app.Id, models.ActionCreate); err != nil {
		panic(err)
	}

	c.Flash.Success("Created!")
	return c.Redirect(routes.AppControllerWithValidation.GetApp(app.Id))
}

// ------------------------------------------------------
// AppControllerWithValidation
func (c AppControllerWithValidation) GetApp(appId int) revel.Result {
	app := c.App

	authorities, err := app.Authorities(Dbm)
	if err != nil {
		panic(err)
	}

	bundles, err := app.Bundles(Dbm)
	if err != nil {
		panic(err)
	}

	return c.Render(app, authorities, bundles)
}

func (c AppControllerWithValidation) GetUpdateApp(appId int) revel.Result {
	app := c.App
	return c.Render(app)
}

func (c AppControllerWithValidation) PostUpdateApp(appId int, app models.App) revel.Result {
	if appId != app.Id {
		c.Flash.Error("Parameter is invalid.")
		c.Redirect(routes.AppControllerWithValidation.GetUpdateApp(app.Id))
	}

	c.Validation.Required(app.Title).Message("Title is required.")
	if c.Validation.HasErrors() {
		c.Validation.Keep()
		c.FlashParams()
		return c.Redirect(routes.AppControllerWithValidation.GetUpdateApp(app.Id))
	}

	err := Transact(func(txn gorp.SqlExecutor) error {
		return app.Update(txn)
	})
	if err != nil {
		panic(err)
	}

	if err := c.GoogleService.UpdateFileTitle(c.App.FileId, app.Title); err != nil {
		panic(err)
	}

	c.Flash.Success("Updated!")
	return c.Redirect(routes.AppControllerWithValidation.GetApp(app.Id))
}

func (c AppControllerWithValidation) PostRefreshToken(appId int, app models.App) revel.Result {
	if appId != app.Id {
		c.Flash.Error("Parameter is invalid")
		c.Redirect(routes.AppControllerWithValidation.GetApp(app.Id))
	}

	err := Transact(func(txn gorp.SqlExecutor) error {
		return app.RefreshToken(txn)
	})
	if err != nil {
		panic(err)
	}

	c.Flash.Success("Refreshed!")
	return c.Redirect(routes.AppControllerWithValidation.GetApp(app.Id))
}

func (c AppControllerWithValidation) PostDeleteApp(appId int) revel.Result {
	app := c.App

	err := Transact(func(txn gorp.SqlExecutor) error {
		return app.Delete(txn, c.GoogleService)
	})
	if err != nil {
		panic(err)
	}

	if err := c.createAudit(models.ResourceApp, appId, models.ActionDelete); err != nil {
		panic(err)
	}

	c.Flash.Success("Deleted!")
	return c.Redirect(routes.AlphaWingController.Index())
}

func (c AppControllerWithValidation) GetCreateBundle(appId int) revel.Result {
	app := c.App
	bundle := &models.Bundle{AppId: appId}
	return c.Render(app, bundle)
}

func (c AppControllerWithValidation) PostCreateBundle(appId int, bundle models.Bundle, file *os.File) revel.Result {
	if appId != bundle.AppId {
		c.Flash.Error("Parameter is invalid.")
		c.Redirect(routes.AppControllerWithValidation.GetApp(appId))
	}

	c.Validation.Required(file != nil).Message("File is required.")
	if c.Validation.HasErrors() {
		c.Validation.Keep()
		c.FlashParams()
		return c.Redirect(routes.AppControllerWithValidation.GetCreateBundle(appId))
	}

	bundle.File = file
	if _, ok := c.Params.Files["file"]; ok {
		bundle.FileName = c.Params.Files["file"][0].Filename
	}

	err := Transact(func(txn gorp.SqlExecutor) error {
		return c.App.CreateBundle(txn, c.GoogleService, Conf.AaptPath, &bundle)
	})
	if err != nil {
		if aperr, ok := err.(*models.ApkParseError); ok {
			c.Flash.Error(aperr.Error())
			return c.Redirect(routes.AppControllerWithValidation.GetCreateBundle(appId))
		}
		panic(err)
	}

	if err := c.createAudit(models.ResourceBundle, bundle.Id, models.ActionCreate); err != nil {
		panic(err)
	}

	c.Flash.Success("Created!")
	return c.Redirect(routes.BundleControllerWithValidation.GetBundle(bundle.Id))
}

func (c AppControllerWithValidation) PostCreateAuthority(appId int, email string) revel.Result {
	app := c.App

	c.Validation.Required(email).Message("Email is required.")
	c.Validation.Email(email).Message("Email is invalid.")
	if c.Validation.HasErrors() {
		c.Validation.Keep()
		c.FlashParams()
		return c.Redirect(routes.AppControllerWithValidation.GetApp(appId))
	}

	found, err := app.HasAuthorityForEmail(Dbm, email)
	if err != nil {
		panic(err)
	}
	c.Validation.Required(!found).Message(email + " is already registered.")
	if c.Validation.HasErrors() {
		c.Validation.Keep()
		c.FlashParams()
		return c.Redirect(routes.AppControllerWithValidation.GetApp(appId))
	}

	authority := &models.Authority{
		Email: email,
	}

	err = Transact(func(txn gorp.SqlExecutor) error {
		return app.CreateAuthority(txn, c.GoogleService, authority)
	})
	if err != nil {
		panic(err)
	}

	if err := c.createAudit(models.ResourceAuthority, authority.Id, models.ActionCreate); err != nil {
		panic(err)
	}

	c.Flash.Success("Registered!")
	return c.Redirect(routes.AppControllerWithValidation.GetApp(appId))
}

func (c AppControllerWithValidation) PostDeleteAuthority(appId, authorityId int) revel.Result {
	app := c.App

	authority, err := models.GetAuthority(Dbm, authorityId)
	if err != nil {
		panic(err)
	}

	if appId != authority.AppId {
		c.Flash.Error("Parameter is invalid.")
		return c.Redirect(routes.AppControllerWithValidation.GetApp(appId))
	}

	err = Transact(func(txn gorp.SqlExecutor) error {
		return app.DeleteAuthority(txn, c.GoogleService, authority)
	})
	if err != nil {
		panic(err)
	}

	if err := c.createAudit(models.ResourceAuthority, authority.Id, models.ActionDelete); err != nil {
		panic(err)
	}

	c.Flash.Success("Deleted!")
	return c.Redirect(routes.AppControllerWithValidation.GetApp(appId))
}

func (c *AppControllerWithValidation) CheckNotFound() revel.Result {
	param := c.Params.Route["appId"]
	if len(param) == 0 {
		panic(errors.New("AppId is Required."))
	}
	appId, err := strconv.Atoi(param[0])
	if err != nil {
		panic(err)
	}
	app, err := models.GetApp(Dbm, appId)
	if err != nil {
		if err == sql.ErrNoRows {
			return c.NotFound("NotFound")
		}
		panic(err)
	}
	c.App = app
	return nil
}

func (c *AppControllerWithValidation) CheckForbidden() revel.Result {
	if c.App == nil {
		c.NotFound("NotFound")
	}
	app := c.App
	s, err := c.userGoogleService()
	if err != nil {
		panic(err)
	}
	_, err = s.GetFile(app.FileId)
	if err != nil {
		return c.Forbidden("Forbidden")
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/st3v/translator/microsoft"
)

func main() {
	translator := microsoft.NewTranslator("globe", "gQwodqYqfffKHRCh/3iudM7k/7I0JoqcvSc8fH4Dpf0=")
	fmt.Println(translator.Translate("Hello World!", "en", "de"))
}
<commit_msg>Remove credentials from example<commit_after>package main

import (
	"fmt"

	"github.com/st3v/translator/microsoft"
)

func main() {
	translator := microsoft.NewTranslator("client-id", "client-secret")
	fmt.Println(translator.Translate("Hello World!", "en", "de"))
}
<|endoftext|>