Codebase list golang-github-go-kit-kit / 0c243515-0bf2-4b25-8735-9c1038fa7c1b/v0.7.0 examples / stringsvc1 / main.go
0c243515-0bf2-4b25-8735-9c1038fa7c1b/v0.7.0

Tree @0c243515-0bf2-4b25-8735-9c1038fa7c1b/v0.7.0 (Download .tar.gz)

main.go @0c243515-0bf2-4b25-8735-9c1038fa7c1b/v0.7.0

1ed136b
 
 
4a29204
1ed136b
 
 
 
 
 
 
 
 
 
 
 
ebf82f4
 
1ed136b
 
ebf82f4
1ed136b
 
ebf82f4
1ed136b
 
 
 
 
 
ebf82f4
1ed136b
 
 
ebf82f4
 
1ed136b
ebf82f4
 
 
 
1ed136b
ebf82f4
 
 
 
1ed136b
ebf82f4
 
1ed136b
 
ebf82f4
 
 
 
 
1ed136b
 
 
ebf82f4
e103562
 
 
 
1ed136b
 
 
 
 
 
ebf82f4
1ed136b
 
 
 
ebf82f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5f48909
1ed136b
bcbfb94
1ed136b
 
 
 
 
5f48909
1ed136b
bcbfb94
1ed136b
 
 
 
 
5f48909
1ed136b
 
package main

import (
	"context"
	"encoding/json"
	"errors"
	"log"
	"net/http"
	"strings"

	"github.com/go-kit/kit/endpoint"
	httptransport "github.com/go-kit/kit/transport/http"
)

// StringService provides operations on strings.
type StringService interface {
	Uppercase(context.Context, string) (string, error)
	Count(context.Context, string) int
}

// stringService is a concrete implementation of StringService
type stringService struct{}

func (stringService) Uppercase(_ context.Context, s string) (string, error) {
	if s == "" {
		return "", ErrEmpty
	}
	return strings.ToUpper(s), nil
}

func (stringService) Count(_ context.Context, s string) int {
	return len(s)
}

// ErrEmpty is returned when an input string is empty.
var ErrEmpty = errors.New("empty string")

// For each method, we define request and response structs
type uppercaseRequest struct {
	S string `json:"s"`
}

type uppercaseResponse struct {
	V   string `json:"v"`
	Err string `json:"err,omitempty"` // errors don't define JSON marshaling
}

type countRequest struct {
	S string `json:"s"`
}

type countResponse struct {
	V int `json:"v"`
}

// Endpoints are a primary abstraction in go-kit. An endpoint represents a single RPC (method in our service interface)
func makeUppercaseEndpoint(svc StringService) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (interface{}, error) {
		req := request.(uppercaseRequest)
		v, err := svc.Uppercase(ctx, req.S)
		if err != nil {
			return uppercaseResponse{v, err.Error()}, nil
		}
		return uppercaseResponse{v, ""}, nil
	}
}

func makeCountEndpoint(svc StringService) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (interface{}, error) {
		req := request.(countRequest)
		v := svc.Count(ctx, req.S)
		return countResponse{v}, nil
	}
}

// Transports expose the service to the network. In this first example we utilize JSON over HTTP.
func main() {
	svc := stringService{}

	uppercaseHandler := httptransport.NewServer(
		makeUppercaseEndpoint(svc),
		decodeUppercaseRequest,
		encodeResponse,
	)

	countHandler := httptransport.NewServer(
		makeCountEndpoint(svc),
		decodeCountRequest,
		encodeResponse,
	)

	http.Handle("/uppercase", uppercaseHandler)
	http.Handle("/count", countHandler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

func decodeUppercaseRequest(_ context.Context, r *http.Request) (interface{}, error) {
	var request uppercaseRequest
	if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
		return nil, err
	}
	return request, nil
}

func decodeCountRequest(_ context.Context, r *http.Request) (interface{}, error) {
	var request countRequest
	if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
		return nil, err
	}
	return request, nil
}

func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
	return json.NewEncoder(w).Encode(response)
}