Skip to content
<!DOCTYPE html>
<html>
<head>
<title>Your Order Confirmation</title>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,400,500" rel="stylesheet">
</head>
<style>
body{
font-family: 'Roboto', sans-serif;
}
</style>
<body>
<h2>Your Order Confirmation</h2>
<p>Thanks for shopping with us!<p>
<h3>Order ID</h3>
<p>#{{ order.order_id }}</p>
<h3>Shipping</h3>
<p>#{{ order.shipping_tracking_id }}</p>
<p>{{ order.shipping_cost.units }}. {{ "%02d" | format(order.shipping_cost.nanos // 10000000) }} {{ order.shipping_cost.currency_code }}</p>
<p>{{ order.shipping_address.street_address_1 }}, {{order.shipping_address.street_address_2}}, {{order.shipping_address.city}}, {{order.shipping_address.country}} {{order.shipping_address.zip_code}}</p>
<h3>Items</h3>
<table style="width:100%">
<tr>
<th>Item No.</th>
<th>Quantity</th>
<th>Price</th>
</tr>
{% for item in order.items %}
<tr>
<td>#{{ item.item.product_id }}</td>
<td>{{ item.item.quantity }}</td>
<td>{{ item.cost.units }}.{{ "%02d" | format(item.cost.nanos // 10000000) }} {{ item.cost.currency_code }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
FROM golang:1.12-alpine as builder
RUN apk add --no-cache ca-certificates git && \
wget -qO/go/bin/dep https://github.com/golang/dep/releases/download/v0.5.0/dep-linux-amd64 && \
chmod +x /go/bin/dep
ENV PROJECT github.com/GoogleCloudPlatform/microservices-demo/src/frontend
WORKDIR /go/src/$PROJECT
# restore dependencies
COPY Gopkg.* ./
RUN dep ensure --vendor-only -v
COPY . .
RUN go install .
FROM alpine as release
RUN apk add --no-cache ca-certificates \
busybox-extras net-tools bind-tools
WORKDIR /frontend
COPY --from=builder /go/bin/frontend /frontend/server
COPY ./templates ./templates
COPY ./static ./static
EXPOSE 8080
ENTRYPOINT ["/frontend/server"]
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:cd61c288406d5d80572967f908a23a1f0ffbf460e926269672e955f4a88b79bc"
name = "cloud.google.com/go"
packages = [
"compute/metadata",
"internal/version",
"monitoring/apiv3",
"profiler",
"trace/apiv2"
]
pruneopts = "UT"
revision = "457ea5c15ccf3b87db582c450e80101989da35f7"
version = "v0.40.0"
[[projects]]
digest = "1:bcd1b2dd631e720b6129e801bf0766c50fb4d39455c0a255047e8fc71c31152f"
name = "contrib.go.opencensus.io/exporter/jaeger"
packages = ["."]
pruneopts = "UT"
revision = "540daef1da72376e9b3e1d52e4f90403d72f5c00"
version = "v0.2.0"
[[projects]]
digest = "1:4b96dcd8534bc6450a922bd16a76360ba3381f0d1daf40abbaec91c053fbfeb5"
name = "contrib.go.opencensus.io/exporter/stackdriver"
packages = ["."]
pruneopts = "UT"
revision = "37aa2801fbf0205003e15636096ebf0373510288"
version = "v0.5.0"
[[projects]]
digest = "1:1d3ad0f6a57c08e2168089a64c34313930571fcbe5359d71c608a97ce504f7ca"
name = "github.com/golang/protobuf"
packages = [
"proto",
"protoc-gen-go/descriptor",
"ptypes",
"ptypes/any",
"ptypes/duration",
"ptypes/empty",
"ptypes/struct",
"ptypes/timestamp",
"ptypes/wrappers"
]
pruneopts = "UT"
revision = "b5d812f8a3706043e23a9cd5babf2e5423744d30"
version = "v1.3.1"
[[projects]]
branch = "master"
digest = "1:dcb1edb161b1b1cac9aedf2a17b9b2c7829e242624968875a3c1b97dd9f4ef00"
name = "github.com/google/pprof"
packages = ["profile"]
pruneopts = "UT"
revision = "54271f7e092ff31b10b7626fee166cbc6304e350"
[[projects]]
digest = "1:582b704bebaa06b48c29b0cec224a6058a09c86883aaddabde889cd1a5f73e1b"
name = "github.com/google/uuid"
packages = ["."]
pruneopts = "UT"
revision = "0cd6bf5da1e1c83f8b45653022c74f71af0538a4"
version = "v1.1.1"
[[projects]]
digest = "1:766102087520f9d54f2acc72bd6637045900ac735b4a419b128d216f0c5c4876"
name = "github.com/googleapis/gax-go"
packages = ["v2"]
pruneopts = "UT"
revision = "bd5b16380fd03dc758d11cef74ba2e3bc8b0e8c2"
version = "v2.0.5"
[[projects]]
digest = "1:cbec35fe4d5a4fba369a656a8cd65e244ea2c743007d8f6c1ccb132acf9d1296"
name = "github.com/gorilla/mux"
packages = ["."]
pruneopts = "UT"
revision = "00bdffe0f3c77e27d2cf6f5c70232a2d3e4d9c15"
version = "v1.7.3"
[[projects]]
digest = "1:31e761d97c76151dde79e9d28964a812c46efc5baee4085b86f68f0c654450de"
name = "github.com/konsorten/go-windows-terminal-sequences"
packages = ["."]
pruneopts = "UT"
revision = "f55edac94c9bbba5d6182a4be46d86a2c9b5b50e"
version = "v1.0.2"
[[projects]]
digest = "1:cf31692c14422fa27c83a05292eb5cbe0fb2775972e8f1f8446a71549bd8980b"
name = "github.com/pkg/errors"
packages = ["."]
pruneopts = "UT"
revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4"
version = "v0.8.1"
[[projects]]
digest = "1:04457f9f6f3ffc5fea48e71d62f2ca256637dee0a04d710288e27e05c8b41976"
name = "github.com/sirupsen/logrus"
packages = ["."]
pruneopts = "UT"
revision = "839c75faf7f98a33d445d181f3018b5c3409a45e"
version = "v1.4.2"
[[projects]]
digest = "1:be83cecd5ba066751e3f789c1faecf5a3229031c7986eb486f593a6e32446ac0"
name = "github.com/uber/jaeger-client-go"
packages = [
"thrift",
"thrift-gen/agent",
"thrift-gen/jaeger",
"thrift-gen/zipkincore"
]
pruneopts = "UT"
revision = "f2e1f58485aacf2975cdde9c9f5396e6d98c35ba"
version = "v2.21.1"
[[projects]]
digest = "1:1bb914cfb78f68f488a91cd7872d3d06a5f83c5bbacf0296dbef44e120b00a91"
name = "go.opencensus.io"
packages = [
".",
"internal",
"internal/tagencoding",
"plugin/ocgrpc",
"plugin/ochttp",
"plugin/ochttp/propagation/b3",
"stats",
"stats/internal",
"stats/view",
"tag",
"trace",
"trace/internal",
"trace/propagation",
"trace/tracestate"
]
pruneopts = "UT"
revision = "b11f239c032624b045c4c2bfd3d1287b4012ce89"
version = "v0.16.0"
[[projects]]
branch = "master"
digest = "1:2f357867bf425774d35beca5be718402a4488b8b23b1563ce8c5bb91d09285a7"
name = "golang.org/x/net"
packages = [
"context",
"context/ctxhttp",
"http/httpguts",
"http2",
"http2/hpack",
"idna",
"internal/timeseries",
"trace"
]
pruneopts = "UT"
revision = "da137c7871d730100384dbcf36e6f8fa493aef5b"
[[projects]]
branch = "master"
digest = "1:31e33f76456ccf54819ab4a646cf01271d1a99d7712ab84bf1a9e7b61cd2031b"
name = "golang.org/x/oauth2"
packages = [
".",
"google",
"internal",
"jws",
"jwt"
]
pruneopts = "UT"
revision = "0f29369cfe4552d0e4bcddc57cc75f4d7e672a33"
[[projects]]
branch = "master"
digest = "1:382bb5a7fb4034db3b6a2d19e5a4a6bcf52f4750530603c01ca18a172fa3089b"
name = "golang.org/x/sync"
packages = ["semaphore"]
pruneopts = "UT"
revision = "112230192c580c3556b8cee6403af37a4fc5f28c"
[[projects]]
branch = "master"
digest = "1:730ba27cd66db3b98ec8f51a6f20d45ec277d490cca36b1f54e31d3fcaf4840e"
name = "golang.org/x/sys"
packages = ["unix"]
pruneopts = "UT"
revision = "04f50cda93cbb67f2afa353c52f342100e80e625"
[[projects]]
digest = "1:8d8faad6b12a3a4c819a3f9618cb6ee1fa1cfc33253abeeea8b55336721e3405"
name = "golang.org/x/text"
packages = [
"collate",
"collate/build",
"internal/colltab",
"internal/gen",
"internal/language",
"internal/language/compact",
"internal/tag",
"internal/triegen",
"internal/ucd",
"language",
"secure/bidirule",
"transform",
"unicode/bidi",
"unicode/cldr",
"unicode/norm",
"unicode/rangetable"
]
pruneopts = "UT"
revision = "342b2e1fbaa52c93f31447ad2c6abc048c63e475"
version = "v0.3.2"
[[projects]]
branch = "master"
digest = "1:bc06b12d8436550fccc0212037e9281a7e4d53db25c2349eb3cc6c3457e0406b"
name = "google.golang.org/api"
packages = [
"googleapi/transport",
"internal",
"iterator",
"option",
"support/bundler",
"transport",
"transport/grpc",
"transport/http",
"transport/http/internal/propagation"
]
pruneopts = "UT"
revision = "aae1d1b89c27132abe4fa22731a2a61e7089079c"
[[projects]]
digest = "1:2c26b1c47556c0e5e73cdb05d8361c463737eee4baac35d38b40c728c3074a94"
name = "google.golang.org/appengine"
packages = [
".",
"internal",
"internal/app_identity",
"internal/base",
"internal/datastore",
"internal/log",
"internal/modules",
"internal/remote_api",
"internal/socket",
"internal/urlfetch",
"socket",
"urlfetch"
]
pruneopts = "UT"
revision = "b2f4a3cf3c67576a2ee09e1fe62656a5086ce880"
version = "v1.6.1"
[[projects]]
branch = "master"
digest = "1:cb0f37e3cdf50a27abbf33a48797b30786239d4fd69dbfbbc63cfa19d400d3ce"
name = "google.golang.org/genproto"
packages = [
"googleapis/api",
"googleapis/api/annotations",
"googleapis/api/distribution",
"googleapis/api/label",
"googleapis/api/metric",
"googleapis/api/monitoredres",
"googleapis/devtools/cloudprofiler/v2",
"googleapis/devtools/cloudtrace/v2",
"googleapis/monitoring/v3",
"googleapis/rpc/errdetails",
"googleapis/rpc/status",
"protobuf/field_mask"
]
pruneopts = "UT"
revision = "3bdd9d9f5532d75d09efb230bd767d265245cfe5"
[[projects]]
digest = "1:94dd3fb42315b97533bb74fe15498905734bc3a3c6e692dc7839fec749d44d26"
name = "google.golang.org/grpc"
packages = [
".",
"balancer",
"balancer/base",
"balancer/grpclb",
"balancer/grpclb/grpc_lb_v1",
"balancer/roundrobin",
"binarylog/grpc_binarylog_v1",
"codes",
"connectivity",
"credentials",
"credentials/alts",
"credentials/alts/internal",
"credentials/alts/internal/authinfo",
"credentials/alts/internal/conn",
"credentials/alts/internal/handshaker",
"credentials/alts/internal/handshaker/service",
"credentials/alts/internal/proto/grpc_gcp",
"credentials/google",
"credentials/internal",
"credentials/oauth",
"encoding",
"encoding/proto",
"grpclog",
"internal",
"internal/backoff",
"internal/balancerload",
"internal/binarylog",
"internal/channelz",
"internal/envconfig",
"internal/grpcrand",
"internal/grpcsync",
"internal/syscall",
"internal/transport",
"keepalive",
"metadata",
"naming",
"peer",
"resolver",
"resolver/dns",
"resolver/passthrough",
"serviceconfig",
"stats",
"status",
"tap"
]
pruneopts = "UT"
revision = "1d89a3c832915b2314551c1d2a506874d62e53f7"
version = "v1.22.0"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"cloud.google.com/go/profiler",
"contrib.go.opencensus.io/exporter/jaeger",
"contrib.go.opencensus.io/exporter/stackdriver",
"github.com/golang/protobuf/proto",
"github.com/google/uuid",
"github.com/gorilla/mux",
"github.com/pkg/errors",
"github.com/sirupsen/logrus",
"go.opencensus.io/plugin/ocgrpc",
"go.opencensus.io/plugin/ochttp",
"go.opencensus.io/plugin/ochttp/propagation/b3",
"go.opencensus.io/stats/view",
"go.opencensus.io/trace",
"golang.org/x/net/context",
"google.golang.org/grpc"
]
solver-name = "gps-cdcl"
solver-version = 1
# Gopkg.toml example
#
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true
[[constraint]]
name = "cloud.google.com/go"
version = "0.40.0"
[[constraint]]
name = "contrib.go.opencensus.io/exporter/stackdriver"
version = "0.5.0"
[[constraint]]
name = "github.com/golang/protobuf"
version = "1.2.0"
[[constraint]]
name = "github.com/google/uuid"
version = "1.0.0"
[[constraint]]
name = "github.com/gorilla/mux"
version = "1.6.2"
[[constraint]]
name = "github.com/pkg/errors"
version = "0.8.0"
[[constraint]]
name = "github.com/sirupsen/logrus"
version = "1.0.6"
[[constraint]]
name = "go.opencensus.io"
version = "0.16.0"
[[constraint]]
branch = "master"
name = "golang.org/x/net"
[prune]
go-tests = true
unused-packages = true
[[constraint]]
name = "contrib.go.opencensus.io/exporter/jaeger"
version = "0.2.0"
# frontend
Run the following command to restore dependencies to `vendor/` directory:
dep ensure --vendor-only
#!/bin/bash -eu
#
# Copyright 2018 Google LLC
#
# 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.
#!/bin/bash -e
PATH=$PATH:$GOPATH/bin
protodir=../../pb
protoc --go_out=plugins=grpc:genproto -I $protodir $protodir/demo.proto
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: demo.proto
package hipstershop
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type CartItem struct {
ProductId string `protobuf:"bytes,1,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"`
Quantity int32 `protobuf:"varint,2,opt,name=quantity,proto3" json:"quantity,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CartItem) Reset() { *m = CartItem{} }
func (m *CartItem) String() string { return proto.CompactTextString(m) }
func (*CartItem) ProtoMessage() {}
func (*CartItem) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{0}
}
func (m *CartItem) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CartItem.Unmarshal(m, b)
}
func (m *CartItem) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CartItem.Marshal(b, m, deterministic)
}
func (m *CartItem) XXX_Merge(src proto.Message) {
xxx_messageInfo_CartItem.Merge(m, src)
}
func (m *CartItem) XXX_Size() int {
return xxx_messageInfo_CartItem.Size(m)
}
func (m *CartItem) XXX_DiscardUnknown() {
xxx_messageInfo_CartItem.DiscardUnknown(m)
}
var xxx_messageInfo_CartItem proto.InternalMessageInfo
func (m *CartItem) GetProductId() string {
if m != nil {
return m.ProductId
}
return ""
}
func (m *CartItem) GetQuantity() int32 {
if m != nil {
return m.Quantity
}
return 0
}
type AddItemRequest struct {
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
Item *CartItem `protobuf:"bytes,2,opt,name=item,proto3" json:"item,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *AddItemRequest) Reset() { *m = AddItemRequest{} }
func (m *AddItemRequest) String() string { return proto.CompactTextString(m) }
func (*AddItemRequest) ProtoMessage() {}
func (*AddItemRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{1}
}
func (m *AddItemRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_AddItemRequest.Unmarshal(m, b)
}
func (m *AddItemRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_AddItemRequest.Marshal(b, m, deterministic)
}
func (m *AddItemRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_AddItemRequest.Merge(m, src)
}
func (m *AddItemRequest) XXX_Size() int {
return xxx_messageInfo_AddItemRequest.Size(m)
}
func (m *AddItemRequest) XXX_DiscardUnknown() {
xxx_messageInfo_AddItemRequest.DiscardUnknown(m)
}
var xxx_messageInfo_AddItemRequest proto.InternalMessageInfo
func (m *AddItemRequest) GetUserId() string {
if m != nil {
return m.UserId
}
return ""
}
func (m *AddItemRequest) GetItem() *CartItem {
if m != nil {
return m.Item
}
return nil
}
type EmptyCartRequest struct {
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *EmptyCartRequest) Reset() { *m = EmptyCartRequest{} }
func (m *EmptyCartRequest) String() string { return proto.CompactTextString(m) }
func (*EmptyCartRequest) ProtoMessage() {}
func (*EmptyCartRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{2}
}
func (m *EmptyCartRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_EmptyCartRequest.Unmarshal(m, b)
}
func (m *EmptyCartRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_EmptyCartRequest.Marshal(b, m, deterministic)
}
func (m *EmptyCartRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_EmptyCartRequest.Merge(m, src)
}
func (m *EmptyCartRequest) XXX_Size() int {
return xxx_messageInfo_EmptyCartRequest.Size(m)
}
func (m *EmptyCartRequest) XXX_DiscardUnknown() {
xxx_messageInfo_EmptyCartRequest.DiscardUnknown(m)
}
var xxx_messageInfo_EmptyCartRequest proto.InternalMessageInfo
func (m *EmptyCartRequest) GetUserId() string {
if m != nil {
return m.UserId
}
return ""
}
type GetCartRequest struct {
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetCartRequest) Reset() { *m = GetCartRequest{} }
func (m *GetCartRequest) String() string { return proto.CompactTextString(m) }
func (*GetCartRequest) ProtoMessage() {}
func (*GetCartRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{3}
}
func (m *GetCartRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetCartRequest.Unmarshal(m, b)
}
func (m *GetCartRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetCartRequest.Marshal(b, m, deterministic)
}
func (m *GetCartRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetCartRequest.Merge(m, src)
}
func (m *GetCartRequest) XXX_Size() int {
return xxx_messageInfo_GetCartRequest.Size(m)
}
func (m *GetCartRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetCartRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetCartRequest proto.InternalMessageInfo
func (m *GetCartRequest) GetUserId() string {
if m != nil {
return m.UserId
}
return ""
}
type Cart struct {
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
Items []*CartItem `protobuf:"bytes,2,rep,name=items,proto3" json:"items,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Cart) Reset() { *m = Cart{} }
func (m *Cart) String() string { return proto.CompactTextString(m) }
func (*Cart) ProtoMessage() {}
func (*Cart) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{4}
}
func (m *Cart) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Cart.Unmarshal(m, b)
}
func (m *Cart) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Cart.Marshal(b, m, deterministic)
}
func (m *Cart) XXX_Merge(src proto.Message) {
xxx_messageInfo_Cart.Merge(m, src)
}
func (m *Cart) XXX_Size() int {
return xxx_messageInfo_Cart.Size(m)
}
func (m *Cart) XXX_DiscardUnknown() {
xxx_messageInfo_Cart.DiscardUnknown(m)
}
var xxx_messageInfo_Cart proto.InternalMessageInfo
func (m *Cart) GetUserId() string {
if m != nil {
return m.UserId
}
return ""
}
func (m *Cart) GetItems() []*CartItem {
if m != nil {
return m.Items
}
return nil
}
type Empty struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Empty) Reset() { *m = Empty{} }
func (m *Empty) String() string { return proto.CompactTextString(m) }
func (*Empty) ProtoMessage() {}
func (*Empty) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{5}
}
func (m *Empty) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Empty.Unmarshal(m, b)
}
func (m *Empty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Empty.Marshal(b, m, deterministic)
}
func (m *Empty) XXX_Merge(src proto.Message) {
xxx_messageInfo_Empty.Merge(m, src)
}
func (m *Empty) XXX_Size() int {
return xxx_messageInfo_Empty.Size(m)
}
func (m *Empty) XXX_DiscardUnknown() {
xxx_messageInfo_Empty.DiscardUnknown(m)
}
var xxx_messageInfo_Empty proto.InternalMessageInfo
type ListRecommendationsRequest struct {
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
ProductIds []string `protobuf:"bytes,2,rep,name=product_ids,json=productIds,proto3" json:"product_ids,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ListRecommendationsRequest) Reset() { *m = ListRecommendationsRequest{} }
func (m *ListRecommendationsRequest) String() string { return proto.CompactTextString(m) }
func (*ListRecommendationsRequest) ProtoMessage() {}
func (*ListRecommendationsRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{6}
}
func (m *ListRecommendationsRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ListRecommendationsRequest.Unmarshal(m, b)
}
func (m *ListRecommendationsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ListRecommendationsRequest.Marshal(b, m, deterministic)
}
func (m *ListRecommendationsRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_ListRecommendationsRequest.Merge(m, src)
}
func (m *ListRecommendationsRequest) XXX_Size() int {
return xxx_messageInfo_ListRecommendationsRequest.Size(m)
}
func (m *ListRecommendationsRequest) XXX_DiscardUnknown() {
xxx_messageInfo_ListRecommendationsRequest.DiscardUnknown(m)
}
var xxx_messageInfo_ListRecommendationsRequest proto.InternalMessageInfo
func (m *ListRecommendationsRequest) GetUserId() string {
if m != nil {
return m.UserId
}
return ""
}
func (m *ListRecommendationsRequest) GetProductIds() []string {
if m != nil {
return m.ProductIds
}
return nil
}
type ListRecommendationsResponse struct {
ProductIds []string `protobuf:"bytes,1,rep,name=product_ids,json=productIds,proto3" json:"product_ids,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ListRecommendationsResponse) Reset() { *m = ListRecommendationsResponse{} }
func (m *ListRecommendationsResponse) String() string { return proto.CompactTextString(m) }
func (*ListRecommendationsResponse) ProtoMessage() {}
func (*ListRecommendationsResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{7}
}
func (m *ListRecommendationsResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ListRecommendationsResponse.Unmarshal(m, b)
}
func (m *ListRecommendationsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ListRecommendationsResponse.Marshal(b, m, deterministic)
}
func (m *ListRecommendationsResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_ListRecommendationsResponse.Merge(m, src)
}
func (m *ListRecommendationsResponse) XXX_Size() int {
return xxx_messageInfo_ListRecommendationsResponse.Size(m)
}
func (m *ListRecommendationsResponse) XXX_DiscardUnknown() {
xxx_messageInfo_ListRecommendationsResponse.DiscardUnknown(m)
}
var xxx_messageInfo_ListRecommendationsResponse proto.InternalMessageInfo
func (m *ListRecommendationsResponse) GetProductIds() []string {
if m != nil {
return m.ProductIds
}
return nil
}
type Product struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
Picture string `protobuf:"bytes,4,opt,name=picture,proto3" json:"picture,omitempty"`
PriceUsd *Money `protobuf:"bytes,5,opt,name=price_usd,json=priceUsd,proto3" json:"price_usd,omitempty"`
// Categories such as "vintage" or "gardening" that can be used to look up
// other related products.
Categories []string `protobuf:"bytes,6,rep,name=categories,proto3" json:"categories,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Product) Reset() { *m = Product{} }
func (m *Product) String() string { return proto.CompactTextString(m) }
func (*Product) ProtoMessage() {}
func (*Product) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{8}
}
func (m *Product) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Product.Unmarshal(m, b)
}
func (m *Product) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Product.Marshal(b, m, deterministic)
}
func (m *Product) XXX_Merge(src proto.Message) {
xxx_messageInfo_Product.Merge(m, src)
}
func (m *Product) XXX_Size() int {
return xxx_messageInfo_Product.Size(m)
}
func (m *Product) XXX_DiscardUnknown() {
xxx_messageInfo_Product.DiscardUnknown(m)
}
var xxx_messageInfo_Product proto.InternalMessageInfo
func (m *Product) GetId() string {
if m != nil {
return m.Id
}
return ""
}
func (m *Product) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *Product) GetDescription() string {
if m != nil {
return m.Description
}
return ""
}
func (m *Product) GetPicture() string {
if m != nil {
return m.Picture
}
return ""
}
func (m *Product) GetPriceUsd() *Money {
if m != nil {
return m.PriceUsd
}
return nil
}
func (m *Product) GetCategories() []string {
if m != nil {
return m.Categories
}
return nil
}
type ListProductsResponse struct {
Products []*Product `protobuf:"bytes,1,rep,name=products,proto3" json:"products,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ListProductsResponse) Reset() { *m = ListProductsResponse{} }
func (m *ListProductsResponse) String() string { return proto.CompactTextString(m) }
func (*ListProductsResponse) ProtoMessage() {}
func (*ListProductsResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{9}
}
func (m *ListProductsResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ListProductsResponse.Unmarshal(m, b)
}
func (m *ListProductsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ListProductsResponse.Marshal(b, m, deterministic)
}
func (m *ListProductsResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_ListProductsResponse.Merge(m, src)
}
func (m *ListProductsResponse) XXX_Size() int {
return xxx_messageInfo_ListProductsResponse.Size(m)
}
func (m *ListProductsResponse) XXX_DiscardUnknown() {
xxx_messageInfo_ListProductsResponse.DiscardUnknown(m)
}
var xxx_messageInfo_ListProductsResponse proto.InternalMessageInfo
func (m *ListProductsResponse) GetProducts() []*Product {
if m != nil {
return m.Products
}
return nil
}
type GetProductRequest struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetProductRequest) Reset() { *m = GetProductRequest{} }
func (m *GetProductRequest) String() string { return proto.CompactTextString(m) }
func (*GetProductRequest) ProtoMessage() {}
func (*GetProductRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{10}
}
func (m *GetProductRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetProductRequest.Unmarshal(m, b)
}
func (m *GetProductRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetProductRequest.Marshal(b, m, deterministic)
}
func (m *GetProductRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetProductRequest.Merge(m, src)
}
func (m *GetProductRequest) XXX_Size() int {
return xxx_messageInfo_GetProductRequest.Size(m)
}
func (m *GetProductRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetProductRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetProductRequest proto.InternalMessageInfo
func (m *GetProductRequest) GetId() string {
if m != nil {
return m.Id
}
return ""
}
type SearchProductsRequest struct {
Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SearchProductsRequest) Reset() { *m = SearchProductsRequest{} }
func (m *SearchProductsRequest) String() string { return proto.CompactTextString(m) }
func (*SearchProductsRequest) ProtoMessage() {}
func (*SearchProductsRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{11}
}
func (m *SearchProductsRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SearchProductsRequest.Unmarshal(m, b)
}
func (m *SearchProductsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SearchProductsRequest.Marshal(b, m, deterministic)
}
func (m *SearchProductsRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_SearchProductsRequest.Merge(m, src)
}
func (m *SearchProductsRequest) XXX_Size() int {
return xxx_messageInfo_SearchProductsRequest.Size(m)
}
func (m *SearchProductsRequest) XXX_DiscardUnknown() {
xxx_messageInfo_SearchProductsRequest.DiscardUnknown(m)
}
var xxx_messageInfo_SearchProductsRequest proto.InternalMessageInfo
func (m *SearchProductsRequest) GetQuery() string {
if m != nil {
return m.Query
}
return ""
}
type SearchProductsResponse struct {
Results []*Product `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SearchProductsResponse) Reset() { *m = SearchProductsResponse{} }
func (m *SearchProductsResponse) String() string { return proto.CompactTextString(m) }
func (*SearchProductsResponse) ProtoMessage() {}
func (*SearchProductsResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{12}
}
func (m *SearchProductsResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SearchProductsResponse.Unmarshal(m, b)
}
func (m *SearchProductsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SearchProductsResponse.Marshal(b, m, deterministic)
}
func (m *SearchProductsResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_SearchProductsResponse.Merge(m, src)
}
func (m *SearchProductsResponse) XXX_Size() int {
return xxx_messageInfo_SearchProductsResponse.Size(m)
}
func (m *SearchProductsResponse) XXX_DiscardUnknown() {
xxx_messageInfo_SearchProductsResponse.DiscardUnknown(m)
}
var xxx_messageInfo_SearchProductsResponse proto.InternalMessageInfo
func (m *SearchProductsResponse) GetResults() []*Product {
if m != nil {
return m.Results
}
return nil
}
type GetQuoteRequest struct {
Address *Address `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
Items []*CartItem `protobuf:"bytes,2,rep,name=items,proto3" json:"items,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetQuoteRequest) Reset() { *m = GetQuoteRequest{} }
func (m *GetQuoteRequest) String() string { return proto.CompactTextString(m) }
func (*GetQuoteRequest) ProtoMessage() {}
func (*GetQuoteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{13}
}
func (m *GetQuoteRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetQuoteRequest.Unmarshal(m, b)
}
func (m *GetQuoteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetQuoteRequest.Marshal(b, m, deterministic)
}
func (m *GetQuoteRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetQuoteRequest.Merge(m, src)
}
func (m *GetQuoteRequest) XXX_Size() int {
return xxx_messageInfo_GetQuoteRequest.Size(m)
}
func (m *GetQuoteRequest) XXX_DiscardUnknown() {
xxx_messageInfo_GetQuoteRequest.DiscardUnknown(m)
}
var xxx_messageInfo_GetQuoteRequest proto.InternalMessageInfo
func (m *GetQuoteRequest) GetAddress() *Address {
if m != nil {
return m.Address
}
return nil
}
func (m *GetQuoteRequest) GetItems() []*CartItem {
if m != nil {
return m.Items
}
return nil
}
type GetQuoteResponse struct {
CostUsd *Money `protobuf:"bytes,1,opt,name=cost_usd,json=costUsd,proto3" json:"cost_usd,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetQuoteResponse) Reset() { *m = GetQuoteResponse{} }
func (m *GetQuoteResponse) String() string { return proto.CompactTextString(m) }
func (*GetQuoteResponse) ProtoMessage() {}
func (*GetQuoteResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{14}
}
func (m *GetQuoteResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetQuoteResponse.Unmarshal(m, b)
}
func (m *GetQuoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetQuoteResponse.Marshal(b, m, deterministic)
}
func (m *GetQuoteResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetQuoteResponse.Merge(m, src)
}
func (m *GetQuoteResponse) XXX_Size() int {
return xxx_messageInfo_GetQuoteResponse.Size(m)
}
func (m *GetQuoteResponse) XXX_DiscardUnknown() {
xxx_messageInfo_GetQuoteResponse.DiscardUnknown(m)
}
var xxx_messageInfo_GetQuoteResponse proto.InternalMessageInfo
func (m *GetQuoteResponse) GetCostUsd() *Money {
if m != nil {
return m.CostUsd
}
return nil
}
type ShipOrderRequest struct {
Address *Address `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
Items []*CartItem `protobuf:"bytes,2,rep,name=items,proto3" json:"items,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ShipOrderRequest) Reset() { *m = ShipOrderRequest{} }
func (m *ShipOrderRequest) String() string { return proto.CompactTextString(m) }
func (*ShipOrderRequest) ProtoMessage() {}
func (*ShipOrderRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{15}
}
func (m *ShipOrderRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ShipOrderRequest.Unmarshal(m, b)
}
func (m *ShipOrderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ShipOrderRequest.Marshal(b, m, deterministic)
}
func (m *ShipOrderRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_ShipOrderRequest.Merge(m, src)
}
func (m *ShipOrderRequest) XXX_Size() int {
return xxx_messageInfo_ShipOrderRequest.Size(m)
}
func (m *ShipOrderRequest) XXX_DiscardUnknown() {
xxx_messageInfo_ShipOrderRequest.DiscardUnknown(m)
}
var xxx_messageInfo_ShipOrderRequest proto.InternalMessageInfo
func (m *ShipOrderRequest) GetAddress() *Address {
if m != nil {
return m.Address
}
return nil
}
func (m *ShipOrderRequest) GetItems() []*CartItem {
if m != nil {
return m.Items
}
return nil
}
type ShipOrderResponse struct {
TrackingId string `protobuf:"bytes,1,opt,name=tracking_id,json=trackingId,proto3" json:"tracking_id,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ShipOrderResponse) Reset() { *m = ShipOrderResponse{} }
func (m *ShipOrderResponse) String() string { return proto.CompactTextString(m) }
func (*ShipOrderResponse) ProtoMessage() {}
func (*ShipOrderResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{16}
}
func (m *ShipOrderResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ShipOrderResponse.Unmarshal(m, b)
}
func (m *ShipOrderResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ShipOrderResponse.Marshal(b, m, deterministic)
}
func (m *ShipOrderResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_ShipOrderResponse.Merge(m, src)
}
func (m *ShipOrderResponse) XXX_Size() int {
return xxx_messageInfo_ShipOrderResponse.Size(m)
}
func (m *ShipOrderResponse) XXX_DiscardUnknown() {
xxx_messageInfo_ShipOrderResponse.DiscardUnknown(m)
}
var xxx_messageInfo_ShipOrderResponse proto.InternalMessageInfo
func (m *ShipOrderResponse) GetTrackingId() string {
if m != nil {
return m.TrackingId
}
return ""
}
type Address struct {
StreetAddress string `protobuf:"bytes,1,opt,name=street_address,json=streetAddress,proto3" json:"street_address,omitempty"`
City string `protobuf:"bytes,2,opt,name=city,proto3" json:"city,omitempty"`
State string `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"`
Country string `protobuf:"bytes,4,opt,name=country,proto3" json:"country,omitempty"`
ZipCode int32 `protobuf:"varint,5,opt,name=zip_code,json=zipCode,proto3" json:"zip_code,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Address) Reset() { *m = Address{} }
func (m *Address) String() string { return proto.CompactTextString(m) }
func (*Address) ProtoMessage() {}
func (*Address) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{17}
}
func (m *Address) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Address.Unmarshal(m, b)
}
func (m *Address) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Address.Marshal(b, m, deterministic)
}
func (m *Address) XXX_Merge(src proto.Message) {
xxx_messageInfo_Address.Merge(m, src)
}
func (m *Address) XXX_Size() int {
return xxx_messageInfo_Address.Size(m)
}
func (m *Address) XXX_DiscardUnknown() {
xxx_messageInfo_Address.DiscardUnknown(m)
}
var xxx_messageInfo_Address proto.InternalMessageInfo
func (m *Address) GetStreetAddress() string {
if m != nil {
return m.StreetAddress
}
return ""
}
func (m *Address) GetCity() string {
if m != nil {
return m.City
}
return ""
}
func (m *Address) GetState() string {
if m != nil {
return m.State
}
return ""
}
func (m *Address) GetCountry() string {
if m != nil {
return m.Country
}
return ""
}
func (m *Address) GetZipCode() int32 {
if m != nil {
return m.ZipCode
}
return 0
}
// Represents an amount of money with its currency type.
type Money struct {
// The 3-letter currency code defined in ISO 4217.
CurrencyCode string `protobuf:"bytes,1,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"`
// The whole units of the amount.
// For example if `currencyCode` is `"USD"`, then 1 unit is one US dollar.
Units int64 `protobuf:"varint,2,opt,name=units,proto3" json:"units,omitempty"`
// Number of nano (10^-9) units of the amount.
// The value must be between -999,999,999 and +999,999,999 inclusive.
// If `units` is positive, `nanos` must be positive or zero.
// If `units` is zero, `nanos` can be positive, zero, or negative.
// If `units` is negative, `nanos` must be negative or zero.
// For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.
Nanos int32 `protobuf:"varint,3,opt,name=nanos,proto3" json:"nanos,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Money) Reset() { *m = Money{} }
func (m *Money) String() string { return proto.CompactTextString(m) }
func (*Money) ProtoMessage() {}
func (*Money) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{18}
}
func (m *Money) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Money.Unmarshal(m, b)
}
func (m *Money) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Money.Marshal(b, m, deterministic)
}
func (m *Money) XXX_Merge(src proto.Message) {
xxx_messageInfo_Money.Merge(m, src)
}
func (m *Money) XXX_Size() int {
return xxx_messageInfo_Money.Size(m)
}
func (m *Money) XXX_DiscardUnknown() {
xxx_messageInfo_Money.DiscardUnknown(m)
}
var xxx_messageInfo_Money proto.InternalMessageInfo
func (m *Money) GetCurrencyCode() string {
if m != nil {
return m.CurrencyCode
}
return ""
}
func (m *Money) GetUnits() int64 {
if m != nil {
return m.Units
}
return 0
}
func (m *Money) GetNanos() int32 {
if m != nil {
return m.Nanos
}
return 0
}
type GetSupportedCurrenciesResponse struct {
// The 3-letter currency code defined in ISO 4217.
CurrencyCodes []string `protobuf:"bytes,1,rep,name=currency_codes,json=currencyCodes,proto3" json:"currency_codes,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetSupportedCurrenciesResponse) Reset() { *m = GetSupportedCurrenciesResponse{} }
func (m *GetSupportedCurrenciesResponse) String() string { return proto.CompactTextString(m) }
func (*GetSupportedCurrenciesResponse) ProtoMessage() {}
func (*GetSupportedCurrenciesResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{19}
}
func (m *GetSupportedCurrenciesResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetSupportedCurrenciesResponse.Unmarshal(m, b)
}
func (m *GetSupportedCurrenciesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetSupportedCurrenciesResponse.Marshal(b, m, deterministic)
}
func (m *GetSupportedCurrenciesResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetSupportedCurrenciesResponse.Merge(m, src)
}
func (m *GetSupportedCurrenciesResponse) XXX_Size() int {
return xxx_messageInfo_GetSupportedCurrenciesResponse.Size(m)
}
func (m *GetSupportedCurrenciesResponse) XXX_DiscardUnknown() {
xxx_messageInfo_GetSupportedCurrenciesResponse.DiscardUnknown(m)
}
var xxx_messageInfo_GetSupportedCurrenciesResponse proto.InternalMessageInfo
func (m *GetSupportedCurrenciesResponse) GetCurrencyCodes() []string {
if m != nil {
return m.CurrencyCodes
}
return nil
}
type CurrencyConversionRequest struct {
From *Money `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"`
// The 3-letter currency code defined in ISO 4217.
ToCode string `protobuf:"bytes,2,opt,name=to_code,json=toCode,proto3" json:"to_code,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CurrencyConversionRequest) Reset() { *m = CurrencyConversionRequest{} }
func (m *CurrencyConversionRequest) String() string { return proto.CompactTextString(m) }
func (*CurrencyConversionRequest) ProtoMessage() {}
func (*CurrencyConversionRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{20}
}
func (m *CurrencyConversionRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CurrencyConversionRequest.Unmarshal(m, b)
}
func (m *CurrencyConversionRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CurrencyConversionRequest.Marshal(b, m, deterministic)
}
func (m *CurrencyConversionRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_CurrencyConversionRequest.Merge(m, src)
}
func (m *CurrencyConversionRequest) XXX_Size() int {
return xxx_messageInfo_CurrencyConversionRequest.Size(m)
}
func (m *CurrencyConversionRequest) XXX_DiscardUnknown() {
xxx_messageInfo_CurrencyConversionRequest.DiscardUnknown(m)
}
var xxx_messageInfo_CurrencyConversionRequest proto.InternalMessageInfo
func (m *CurrencyConversionRequest) GetFrom() *Money {
if m != nil {
return m.From
}
return nil
}
func (m *CurrencyConversionRequest) GetToCode() string {
if m != nil {
return m.ToCode
}
return ""
}
type CreditCardInfo struct {
CreditCardNumber string `protobuf:"bytes,1,opt,name=credit_card_number,json=creditCardNumber,proto3" json:"credit_card_number,omitempty"`
CreditCardCvv int32 `protobuf:"varint,2,opt,name=credit_card_cvv,json=creditCardCvv,proto3" json:"credit_card_cvv,omitempty"`
CreditCardExpirationYear int32 `protobuf:"varint,3,opt,name=credit_card_expiration_year,json=creditCardExpirationYear,proto3" json:"credit_card_expiration_year,omitempty"`
CreditCardExpirationMonth int32 `protobuf:"varint,4,opt,name=credit_card_expiration_month,json=creditCardExpirationMonth,proto3" json:"credit_card_expiration_month,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CreditCardInfo) Reset() { *m = CreditCardInfo{} }
func (m *CreditCardInfo) String() string { return proto.CompactTextString(m) }
func (*CreditCardInfo) ProtoMessage() {}
func (*CreditCardInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{21}
}
func (m *CreditCardInfo) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CreditCardInfo.Unmarshal(m, b)
}
func (m *CreditCardInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CreditCardInfo.Marshal(b, m, deterministic)
}
func (m *CreditCardInfo) XXX_Merge(src proto.Message) {
xxx_messageInfo_CreditCardInfo.Merge(m, src)
}
func (m *CreditCardInfo) XXX_Size() int {
return xxx_messageInfo_CreditCardInfo.Size(m)
}
func (m *CreditCardInfo) XXX_DiscardUnknown() {
xxx_messageInfo_CreditCardInfo.DiscardUnknown(m)
}
var xxx_messageInfo_CreditCardInfo proto.InternalMessageInfo
func (m *CreditCardInfo) GetCreditCardNumber() string {
if m != nil {
return m.CreditCardNumber
}
return ""
}
func (m *CreditCardInfo) GetCreditCardCvv() int32 {
if m != nil {
return m.CreditCardCvv
}
return 0
}
func (m *CreditCardInfo) GetCreditCardExpirationYear() int32 {
if m != nil {
return m.CreditCardExpirationYear
}
return 0
}
func (m *CreditCardInfo) GetCreditCardExpirationMonth() int32 {
if m != nil {
return m.CreditCardExpirationMonth
}
return 0
}
type ChargeRequest struct {
Amount *Money `protobuf:"bytes,1,opt,name=amount,proto3" json:"amount,omitempty"`
CreditCard *CreditCardInfo `protobuf:"bytes,2,opt,name=credit_card,json=creditCard,proto3" json:"credit_card,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ChargeRequest) Reset() { *m = ChargeRequest{} }
func (m *ChargeRequest) String() string { return proto.CompactTextString(m) }
func (*ChargeRequest) ProtoMessage() {}
func (*ChargeRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{22}
}
func (m *ChargeRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ChargeRequest.Unmarshal(m, b)
}
func (m *ChargeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ChargeRequest.Marshal(b, m, deterministic)
}
func (m *ChargeRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_ChargeRequest.Merge(m, src)
}
func (m *ChargeRequest) XXX_Size() int {
return xxx_messageInfo_ChargeRequest.Size(m)
}
func (m *ChargeRequest) XXX_DiscardUnknown() {
xxx_messageInfo_ChargeRequest.DiscardUnknown(m)
}
var xxx_messageInfo_ChargeRequest proto.InternalMessageInfo
func (m *ChargeRequest) GetAmount() *Money {
if m != nil {
return m.Amount
}
return nil
}
func (m *ChargeRequest) GetCreditCard() *CreditCardInfo {
if m != nil {
return m.CreditCard
}
return nil
}
type ChargeResponse struct {
TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ChargeResponse) Reset() { *m = ChargeResponse{} }
func (m *ChargeResponse) String() string { return proto.CompactTextString(m) }
func (*ChargeResponse) ProtoMessage() {}
func (*ChargeResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{23}
}
func (m *ChargeResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ChargeResponse.Unmarshal(m, b)
}
func (m *ChargeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ChargeResponse.Marshal(b, m, deterministic)
}
func (m *ChargeResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_ChargeResponse.Merge(m, src)
}
func (m *ChargeResponse) XXX_Size() int {
return xxx_messageInfo_ChargeResponse.Size(m)
}
func (m *ChargeResponse) XXX_DiscardUnknown() {
xxx_messageInfo_ChargeResponse.DiscardUnknown(m)
}
var xxx_messageInfo_ChargeResponse proto.InternalMessageInfo
func (m *ChargeResponse) GetTransactionId() string {
if m != nil {
return m.TransactionId
}
return ""
}
type OrderItem struct {
Item *CartItem `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
Cost *Money `protobuf:"bytes,2,opt,name=cost,proto3" json:"cost,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *OrderItem) Reset() { *m = OrderItem{} }
func (m *OrderItem) String() string { return proto.CompactTextString(m) }
func (*OrderItem) ProtoMessage() {}
func (*OrderItem) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{24}
}
func (m *OrderItem) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_OrderItem.Unmarshal(m, b)
}
func (m *OrderItem) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_OrderItem.Marshal(b, m, deterministic)
}
func (m *OrderItem) XXX_Merge(src proto.Message) {
xxx_messageInfo_OrderItem.Merge(m, src)
}
func (m *OrderItem) XXX_Size() int {
return xxx_messageInfo_OrderItem.Size(m)
}
func (m *OrderItem) XXX_DiscardUnknown() {
xxx_messageInfo_OrderItem.DiscardUnknown(m)
}
var xxx_messageInfo_OrderItem proto.InternalMessageInfo
func (m *OrderItem) GetItem() *CartItem {
if m != nil {
return m.Item
}
return nil
}
func (m *OrderItem) GetCost() *Money {
if m != nil {
return m.Cost
}
return nil
}
type OrderResult struct {
OrderId string `protobuf:"bytes,1,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"`
ShippingTrackingId string `protobuf:"bytes,2,opt,name=shipping_tracking_id,json=shippingTrackingId,proto3" json:"shipping_tracking_id,omitempty"`
ShippingCost *Money `protobuf:"bytes,3,opt,name=shipping_cost,json=shippingCost,proto3" json:"shipping_cost,omitempty"`
ShippingAddress *Address `protobuf:"bytes,4,opt,name=shipping_address,json=shippingAddress,proto3" json:"shipping_address,omitempty"`
Items []*OrderItem `protobuf:"bytes,5,rep,name=items,proto3" json:"items,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *OrderResult) Reset() { *m = OrderResult{} }
func (m *OrderResult) String() string { return proto.CompactTextString(m) }
func (*OrderResult) ProtoMessage() {}
func (*OrderResult) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{25}
}
func (m *OrderResult) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_OrderResult.Unmarshal(m, b)
}
func (m *OrderResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_OrderResult.Marshal(b, m, deterministic)
}
func (m *OrderResult) XXX_Merge(src proto.Message) {
xxx_messageInfo_OrderResult.Merge(m, src)
}
func (m *OrderResult) XXX_Size() int {
return xxx_messageInfo_OrderResult.Size(m)
}
func (m *OrderResult) XXX_DiscardUnknown() {
xxx_messageInfo_OrderResult.DiscardUnknown(m)
}
var xxx_messageInfo_OrderResult proto.InternalMessageInfo
func (m *OrderResult) GetOrderId() string {
if m != nil {
return m.OrderId
}
return ""
}
func (m *OrderResult) GetShippingTrackingId() string {
if m != nil {
return m.ShippingTrackingId
}
return ""
}
func (m *OrderResult) GetShippingCost() *Money {
if m != nil {
return m.ShippingCost
}
return nil
}
func (m *OrderResult) GetShippingAddress() *Address {
if m != nil {
return m.ShippingAddress
}
return nil
}
func (m *OrderResult) GetItems() []*OrderItem {
if m != nil {
return m.Items
}
return nil
}
type SendOrderConfirmationRequest struct {
Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"`
Order *OrderResult `protobuf:"bytes,2,opt,name=order,proto3" json:"order,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *SendOrderConfirmationRequest) Reset() { *m = SendOrderConfirmationRequest{} }
func (m *SendOrderConfirmationRequest) String() string { return proto.CompactTextString(m) }
func (*SendOrderConfirmationRequest) ProtoMessage() {}
func (*SendOrderConfirmationRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{26}
}
func (m *SendOrderConfirmationRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SendOrderConfirmationRequest.Unmarshal(m, b)
}
func (m *SendOrderConfirmationRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_SendOrderConfirmationRequest.Marshal(b, m, deterministic)
}
func (m *SendOrderConfirmationRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_SendOrderConfirmationRequest.Merge(m, src)
}
func (m *SendOrderConfirmationRequest) XXX_Size() int {
return xxx_messageInfo_SendOrderConfirmationRequest.Size(m)
}
func (m *SendOrderConfirmationRequest) XXX_DiscardUnknown() {
xxx_messageInfo_SendOrderConfirmationRequest.DiscardUnknown(m)
}
var xxx_messageInfo_SendOrderConfirmationRequest proto.InternalMessageInfo
func (m *SendOrderConfirmationRequest) GetEmail() string {
if m != nil {
return m.Email
}
return ""
}
func (m *SendOrderConfirmationRequest) GetOrder() *OrderResult {
if m != nil {
return m.Order
}
return nil
}
type PlaceOrderRequest struct {
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
UserCurrency string `protobuf:"bytes,2,opt,name=user_currency,json=userCurrency,proto3" json:"user_currency,omitempty"`
Address *Address `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
Email string `protobuf:"bytes,5,opt,name=email,proto3" json:"email,omitempty"`
CreditCard *CreditCardInfo `protobuf:"bytes,6,opt,name=credit_card,json=creditCard,proto3" json:"credit_card,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *PlaceOrderRequest) Reset() { *m = PlaceOrderRequest{} }
func (m *PlaceOrderRequest) String() string { return proto.CompactTextString(m) }
func (*PlaceOrderRequest) ProtoMessage() {}
func (*PlaceOrderRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{27}
}
func (m *PlaceOrderRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PlaceOrderRequest.Unmarshal(m, b)
}
func (m *PlaceOrderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_PlaceOrderRequest.Marshal(b, m, deterministic)
}
func (m *PlaceOrderRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_PlaceOrderRequest.Merge(m, src)
}
func (m *PlaceOrderRequest) XXX_Size() int {
return xxx_messageInfo_PlaceOrderRequest.Size(m)
}
func (m *PlaceOrderRequest) XXX_DiscardUnknown() {
xxx_messageInfo_PlaceOrderRequest.DiscardUnknown(m)
}
var xxx_messageInfo_PlaceOrderRequest proto.InternalMessageInfo
func (m *PlaceOrderRequest) GetUserId() string {
if m != nil {
return m.UserId
}
return ""
}
func (m *PlaceOrderRequest) GetUserCurrency() string {
if m != nil {
return m.UserCurrency
}
return ""
}
func (m *PlaceOrderRequest) GetAddress() *Address {
if m != nil {
return m.Address
}
return nil
}
func (m *PlaceOrderRequest) GetEmail() string {
if m != nil {
return m.Email
}
return ""
}
func (m *PlaceOrderRequest) GetCreditCard() *CreditCardInfo {
if m != nil {
return m.CreditCard
}
return nil
}
type PlaceOrderResponse struct {
Order *OrderResult `protobuf:"bytes,1,opt,name=order,proto3" json:"order,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *PlaceOrderResponse) Reset() { *m = PlaceOrderResponse{} }
func (m *PlaceOrderResponse) String() string { return proto.CompactTextString(m) }
func (*PlaceOrderResponse) ProtoMessage() {}
func (*PlaceOrderResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{28}
}
func (m *PlaceOrderResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PlaceOrderResponse.Unmarshal(m, b)
}
func (m *PlaceOrderResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_PlaceOrderResponse.Marshal(b, m, deterministic)
}
func (m *PlaceOrderResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_PlaceOrderResponse.Merge(m, src)
}
func (m *PlaceOrderResponse) XXX_Size() int {
return xxx_messageInfo_PlaceOrderResponse.Size(m)
}
func (m *PlaceOrderResponse) XXX_DiscardUnknown() {
xxx_messageInfo_PlaceOrderResponse.DiscardUnknown(m)
}
var xxx_messageInfo_PlaceOrderResponse proto.InternalMessageInfo
func (m *PlaceOrderResponse) GetOrder() *OrderResult {
if m != nil {
return m.Order
}
return nil
}
type AdRequest struct {
// List of important key words from the current page describing the context.
ContextKeys []string `protobuf:"bytes,1,rep,name=context_keys,json=contextKeys,proto3" json:"context_keys,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *AdRequest) Reset() { *m = AdRequest{} }
func (m *AdRequest) String() string { return proto.CompactTextString(m) }
func (*AdRequest) ProtoMessage() {}
func (*AdRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{29}
}
func (m *AdRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_AdRequest.Unmarshal(m, b)
}
func (m *AdRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_AdRequest.Marshal(b, m, deterministic)
}
func (m *AdRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_AdRequest.Merge(m, src)
}
func (m *AdRequest) XXX_Size() int {
return xxx_messageInfo_AdRequest.Size(m)
}
func (m *AdRequest) XXX_DiscardUnknown() {
xxx_messageInfo_AdRequest.DiscardUnknown(m)
}
var xxx_messageInfo_AdRequest proto.InternalMessageInfo
func (m *AdRequest) GetContextKeys() []string {
if m != nil {
return m.ContextKeys
}
return nil
}
type AdResponse struct {
Ads []*Ad `protobuf:"bytes,1,rep,name=ads,proto3" json:"ads,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *AdResponse) Reset() { *m = AdResponse{} }
func (m *AdResponse) String() string { return proto.CompactTextString(m) }
func (*AdResponse) ProtoMessage() {}
func (*AdResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{30}
}
func (m *AdResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_AdResponse.Unmarshal(m, b)
}
func (m *AdResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_AdResponse.Marshal(b, m, deterministic)
}
func (m *AdResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_AdResponse.Merge(m, src)
}
func (m *AdResponse) XXX_Size() int {
return xxx_messageInfo_AdResponse.Size(m)
}
func (m *AdResponse) XXX_DiscardUnknown() {
xxx_messageInfo_AdResponse.DiscardUnknown(m)
}
var xxx_messageInfo_AdResponse proto.InternalMessageInfo
func (m *AdResponse) GetAds() []*Ad {
if m != nil {
return m.Ads
}
return nil
}
type Ad struct {
// url to redirect to when an ad is clicked.
RedirectUrl string `protobuf:"bytes,1,opt,name=redirect_url,json=redirectUrl,proto3" json:"redirect_url,omitempty"`
// short advertisement text to display.
Text string `protobuf:"bytes,2,opt,name=text,proto3" json:"text,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Ad) Reset() { *m = Ad{} }
func (m *Ad) String() string { return proto.CompactTextString(m) }
func (*Ad) ProtoMessage() {}
func (*Ad) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{31}
}
func (m *Ad) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Ad.Unmarshal(m, b)
}
func (m *Ad) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Ad.Marshal(b, m, deterministic)
}
func (m *Ad) XXX_Merge(src proto.Message) {
xxx_messageInfo_Ad.Merge(m, src)
}
func (m *Ad) XXX_Size() int {
return xxx_messageInfo_Ad.Size(m)
}
func (m *Ad) XXX_DiscardUnknown() {
xxx_messageInfo_Ad.DiscardUnknown(m)
}
var xxx_messageInfo_Ad proto.InternalMessageInfo
func (m *Ad) GetRedirectUrl() string {
if m != nil {
return m.RedirectUrl
}
return ""
}
func (m *Ad) GetText() string {
if m != nil {
return m.Text
}
return ""
}
func init() {
proto.RegisterType((*CartItem)(nil), "hipstershop.CartItem")
proto.RegisterType((*AddItemRequest)(nil), "hipstershop.AddItemRequest")
proto.RegisterType((*EmptyCartRequest)(nil), "hipstershop.EmptyCartRequest")
proto.RegisterType((*GetCartRequest)(nil), "hipstershop.GetCartRequest")
proto.RegisterType((*Cart)(nil), "hipstershop.Cart")
proto.RegisterType((*Empty)(nil), "hipstershop.Empty")
proto.RegisterType((*ListRecommendationsRequest)(nil), "hipstershop.ListRecommendationsRequest")
proto.RegisterType((*ListRecommendationsResponse)(nil), "hipstershop.ListRecommendationsResponse")
proto.RegisterType((*Product)(nil), "hipstershop.Product")
proto.RegisterType((*ListProductsResponse)(nil), "hipstershop.ListProductsResponse")
proto.RegisterType((*GetProductRequest)(nil), "hipstershop.GetProductRequest")
proto.RegisterType((*SearchProductsRequest)(nil), "hipstershop.SearchProductsRequest")
proto.RegisterType((*SearchProductsResponse)(nil), "hipstershop.SearchProductsResponse")
proto.RegisterType((*GetQuoteRequest)(nil), "hipstershop.GetQuoteRequest")
proto.RegisterType((*GetQuoteResponse)(nil), "hipstershop.GetQuoteResponse")
proto.RegisterType((*ShipOrderRequest)(nil), "hipstershop.ShipOrderRequest")
proto.RegisterType((*ShipOrderResponse)(nil), "hipstershop.ShipOrderResponse")
proto.RegisterType((*Address)(nil), "hipstershop.Address")
proto.RegisterType((*Money)(nil), "hipstershop.Money")
proto.RegisterType((*GetSupportedCurrenciesResponse)(nil), "hipstershop.GetSupportedCurrenciesResponse")
proto.RegisterType((*CurrencyConversionRequest)(nil), "hipstershop.CurrencyConversionRequest")
proto.RegisterType((*CreditCardInfo)(nil), "hipstershop.CreditCardInfo")
proto.RegisterType((*ChargeRequest)(nil), "hipstershop.ChargeRequest")
proto.RegisterType((*ChargeResponse)(nil), "hipstershop.ChargeResponse")
proto.RegisterType((*OrderItem)(nil), "hipstershop.OrderItem")
proto.RegisterType((*OrderResult)(nil), "hipstershop.OrderResult")
proto.RegisterType((*SendOrderConfirmationRequest)(nil), "hipstershop.SendOrderConfirmationRequest")
proto.RegisterType((*PlaceOrderRequest)(nil), "hipstershop.PlaceOrderRequest")
proto.RegisterType((*PlaceOrderResponse)(nil), "hipstershop.PlaceOrderResponse")
proto.RegisterType((*AdRequest)(nil), "hipstershop.AdRequest")
proto.RegisterType((*AdResponse)(nil), "hipstershop.AdResponse")
proto.RegisterType((*Ad)(nil), "hipstershop.Ad")
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// CartServiceClient is the client API for CartService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type CartServiceClient interface {
AddItem(ctx context.Context, in *AddItemRequest, opts ...grpc.CallOption) (*Empty, error)
GetCart(ctx context.Context, in *GetCartRequest, opts ...grpc.CallOption) (*Cart, error)
EmptyCart(ctx context.Context, in *EmptyCartRequest, opts ...grpc.CallOption) (*Empty, error)
}
type cartServiceClient struct {
cc *grpc.ClientConn
}
func NewCartServiceClient(cc *grpc.ClientConn) CartServiceClient {
return &cartServiceClient{cc}
}
func (c *cartServiceClient) AddItem(ctx context.Context, in *AddItemRequest, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/hipstershop.CartService/AddItem", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *cartServiceClient) GetCart(ctx context.Context, in *GetCartRequest, opts ...grpc.CallOption) (*Cart, error) {
out := new(Cart)
err := c.cc.Invoke(ctx, "/hipstershop.CartService/GetCart", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *cartServiceClient) EmptyCart(ctx context.Context, in *EmptyCartRequest, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/hipstershop.CartService/EmptyCart", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// CartServiceServer is the server API for CartService service.
type CartServiceServer interface {
AddItem(context.Context, *AddItemRequest) (*Empty, error)
GetCart(context.Context, *GetCartRequest) (*Cart, error)
EmptyCart(context.Context, *EmptyCartRequest) (*Empty, error)
}
func RegisterCartServiceServer(s *grpc.Server, srv CartServiceServer) {
s.RegisterService(&_CartService_serviceDesc, srv)
}
func _CartService_AddItem_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AddItemRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CartServiceServer).AddItem(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.CartService/AddItem",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CartServiceServer).AddItem(ctx, req.(*AddItemRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CartService_GetCart_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetCartRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CartServiceServer).GetCart(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.CartService/GetCart",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CartServiceServer).GetCart(ctx, req.(*GetCartRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CartService_EmptyCart_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(EmptyCartRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CartServiceServer).EmptyCart(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.CartService/EmptyCart",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CartServiceServer).EmptyCart(ctx, req.(*EmptyCartRequest))
}
return interceptor(ctx, in, info, handler)
}
var _CartService_serviceDesc = grpc.ServiceDesc{
ServiceName: "hipstershop.CartService",
HandlerType: (*CartServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "AddItem",
Handler: _CartService_AddItem_Handler,
},
{
MethodName: "GetCart",
Handler: _CartService_GetCart_Handler,
},
{
MethodName: "EmptyCart",
Handler: _CartService_EmptyCart_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "demo.proto",
}
// RecommendationServiceClient is the client API for RecommendationService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type RecommendationServiceClient interface {
ListRecommendations(ctx context.Context, in *ListRecommendationsRequest, opts ...grpc.CallOption) (*ListRecommendationsResponse, error)
}
type recommendationServiceClient struct {
cc *grpc.ClientConn
}
func NewRecommendationServiceClient(cc *grpc.ClientConn) RecommendationServiceClient {
return &recommendationServiceClient{cc}
}
func (c *recommendationServiceClient) ListRecommendations(ctx context.Context, in *ListRecommendationsRequest, opts ...grpc.CallOption) (*ListRecommendationsResponse, error) {
out := new(ListRecommendationsResponse)
err := c.cc.Invoke(ctx, "/hipstershop.RecommendationService/ListRecommendations", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// RecommendationServiceServer is the server API for RecommendationService service.
type RecommendationServiceServer interface {
ListRecommendations(context.Context, *ListRecommendationsRequest) (*ListRecommendationsResponse, error)
}
func RegisterRecommendationServiceServer(s *grpc.Server, srv RecommendationServiceServer) {
s.RegisterService(&_RecommendationService_serviceDesc, srv)
}
func _RecommendationService_ListRecommendations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListRecommendationsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RecommendationServiceServer).ListRecommendations(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.RecommendationService/ListRecommendations",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RecommendationServiceServer).ListRecommendations(ctx, req.(*ListRecommendationsRequest))
}
return interceptor(ctx, in, info, handler)
}
var _RecommendationService_serviceDesc = grpc.ServiceDesc{
ServiceName: "hipstershop.RecommendationService",
HandlerType: (*RecommendationServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ListRecommendations",
Handler: _RecommendationService_ListRecommendations_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "demo.proto",
}
// ProductCatalogServiceClient is the client API for ProductCatalogService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type ProductCatalogServiceClient interface {
ListProducts(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListProductsResponse, error)
GetProduct(ctx context.Context, in *GetProductRequest, opts ...grpc.CallOption) (*Product, error)
SearchProducts(ctx context.Context, in *SearchProductsRequest, opts ...grpc.CallOption) (*SearchProductsResponse, error)
}
type productCatalogServiceClient struct {
cc *grpc.ClientConn
}
func NewProductCatalogServiceClient(cc *grpc.ClientConn) ProductCatalogServiceClient {
return &productCatalogServiceClient{cc}
}
func (c *productCatalogServiceClient) ListProducts(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*ListProductsResponse, error) {
out := new(ListProductsResponse)
err := c.cc.Invoke(ctx, "/hipstershop.ProductCatalogService/ListProducts", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *productCatalogServiceClient) GetProduct(ctx context.Context, in *GetProductRequest, opts ...grpc.CallOption) (*Product, error) {
out := new(Product)
err := c.cc.Invoke(ctx, "/hipstershop.ProductCatalogService/GetProduct", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *productCatalogServiceClient) SearchProducts(ctx context.Context, in *SearchProductsRequest, opts ...grpc.CallOption) (*SearchProductsResponse, error) {
out := new(SearchProductsResponse)
err := c.cc.Invoke(ctx, "/hipstershop.ProductCatalogService/SearchProducts", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ProductCatalogServiceServer is the server API for ProductCatalogService service.
type ProductCatalogServiceServer interface {
ListProducts(context.Context, *Empty) (*ListProductsResponse, error)
GetProduct(context.Context, *GetProductRequest) (*Product, error)
SearchProducts(context.Context, *SearchProductsRequest) (*SearchProductsResponse, error)
}
func RegisterProductCatalogServiceServer(s *grpc.Server, srv ProductCatalogServiceServer) {
s.RegisterService(&_ProductCatalogService_serviceDesc, srv)
}
func _ProductCatalogService_ListProducts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProductCatalogServiceServer).ListProducts(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.ProductCatalogService/ListProducts",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProductCatalogServiceServer).ListProducts(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
func _ProductCatalogService_GetProduct_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetProductRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProductCatalogServiceServer).GetProduct(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.ProductCatalogService/GetProduct",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProductCatalogServiceServer).GetProduct(ctx, req.(*GetProductRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ProductCatalogService_SearchProducts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SearchProductsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProductCatalogServiceServer).SearchProducts(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.ProductCatalogService/SearchProducts",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProductCatalogServiceServer).SearchProducts(ctx, req.(*SearchProductsRequest))
}
return interceptor(ctx, in, info, handler)
}
var _ProductCatalogService_serviceDesc = grpc.ServiceDesc{
ServiceName: "hipstershop.ProductCatalogService",
HandlerType: (*ProductCatalogServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ListProducts",
Handler: _ProductCatalogService_ListProducts_Handler,
},
{
MethodName: "GetProduct",
Handler: _ProductCatalogService_GetProduct_Handler,
},
{
MethodName: "SearchProducts",
Handler: _ProductCatalogService_SearchProducts_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "demo.proto",
}
// ShippingServiceClient is the client API for ShippingService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type ShippingServiceClient interface {
GetQuote(ctx context.Context, in *GetQuoteRequest, opts ...grpc.CallOption) (*GetQuoteResponse, error)
ShipOrder(ctx context.Context, in *ShipOrderRequest, opts ...grpc.CallOption) (*ShipOrderResponse, error)
}
type shippingServiceClient struct {
cc *grpc.ClientConn
}
func NewShippingServiceClient(cc *grpc.ClientConn) ShippingServiceClient {
return &shippingServiceClient{cc}
}
func (c *shippingServiceClient) GetQuote(ctx context.Context, in *GetQuoteRequest, opts ...grpc.CallOption) (*GetQuoteResponse, error) {
out := new(GetQuoteResponse)
err := c.cc.Invoke(ctx, "/hipstershop.ShippingService/GetQuote", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *shippingServiceClient) ShipOrder(ctx context.Context, in *ShipOrderRequest, opts ...grpc.CallOption) (*ShipOrderResponse, error) {
out := new(ShipOrderResponse)
err := c.cc.Invoke(ctx, "/hipstershop.ShippingService/ShipOrder", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ShippingServiceServer is the server API for ShippingService service.
type ShippingServiceServer interface {
GetQuote(context.Context, *GetQuoteRequest) (*GetQuoteResponse, error)
ShipOrder(context.Context, *ShipOrderRequest) (*ShipOrderResponse, error)
}
func RegisterShippingServiceServer(s *grpc.Server, srv ShippingServiceServer) {
s.RegisterService(&_ShippingService_serviceDesc, srv)
}
func _ShippingService_GetQuote_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetQuoteRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ShippingServiceServer).GetQuote(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.ShippingService/GetQuote",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ShippingServiceServer).GetQuote(ctx, req.(*GetQuoteRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ShippingService_ShipOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ShipOrderRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ShippingServiceServer).ShipOrder(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.ShippingService/ShipOrder",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ShippingServiceServer).ShipOrder(ctx, req.(*ShipOrderRequest))
}
return interceptor(ctx, in, info, handler)
}
var _ShippingService_serviceDesc = grpc.ServiceDesc{
ServiceName: "hipstershop.ShippingService",
HandlerType: (*ShippingServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetQuote",
Handler: _ShippingService_GetQuote_Handler,
},
{
MethodName: "ShipOrder",
Handler: _ShippingService_ShipOrder_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "demo.proto",
}
// CurrencyServiceClient is the client API for CurrencyService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type CurrencyServiceClient interface {
GetSupportedCurrencies(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*GetSupportedCurrenciesResponse, error)
Convert(ctx context.Context, in *CurrencyConversionRequest, opts ...grpc.CallOption) (*Money, error)
}
type currencyServiceClient struct {
cc *grpc.ClientConn
}
func NewCurrencyServiceClient(cc *grpc.ClientConn) CurrencyServiceClient {
return &currencyServiceClient{cc}
}
func (c *currencyServiceClient) GetSupportedCurrencies(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*GetSupportedCurrenciesResponse, error) {
out := new(GetSupportedCurrenciesResponse)
err := c.cc.Invoke(ctx, "/hipstershop.CurrencyService/GetSupportedCurrencies", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *currencyServiceClient) Convert(ctx context.Context, in *CurrencyConversionRequest, opts ...grpc.CallOption) (*Money, error) {
out := new(Money)
err := c.cc.Invoke(ctx, "/hipstershop.CurrencyService/Convert", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// CurrencyServiceServer is the server API for CurrencyService service.
type CurrencyServiceServer interface {
GetSupportedCurrencies(context.Context, *Empty) (*GetSupportedCurrenciesResponse, error)
Convert(context.Context, *CurrencyConversionRequest) (*Money, error)
}
func RegisterCurrencyServiceServer(s *grpc.Server, srv CurrencyServiceServer) {
s.RegisterService(&_CurrencyService_serviceDesc, srv)
}
func _CurrencyService_GetSupportedCurrencies_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CurrencyServiceServer).GetSupportedCurrencies(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.CurrencyService/GetSupportedCurrencies",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CurrencyServiceServer).GetSupportedCurrencies(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
func _CurrencyService_Convert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CurrencyConversionRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CurrencyServiceServer).Convert(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.CurrencyService/Convert",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CurrencyServiceServer).Convert(ctx, req.(*CurrencyConversionRequest))
}
return interceptor(ctx, in, info, handler)
}
var _CurrencyService_serviceDesc = grpc.ServiceDesc{
ServiceName: "hipstershop.CurrencyService",
HandlerType: (*CurrencyServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetSupportedCurrencies",
Handler: _CurrencyService_GetSupportedCurrencies_Handler,
},
{
MethodName: "Convert",
Handler: _CurrencyService_Convert_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "demo.proto",
}
// PaymentServiceClient is the client API for PaymentService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type PaymentServiceClient interface {
Charge(ctx context.Context, in *ChargeRequest, opts ...grpc.CallOption) (*ChargeResponse, error)
}
type paymentServiceClient struct {
cc *grpc.ClientConn
}
func NewPaymentServiceClient(cc *grpc.ClientConn) PaymentServiceClient {
return &paymentServiceClient{cc}
}
func (c *paymentServiceClient) Charge(ctx context.Context, in *ChargeRequest, opts ...grpc.CallOption) (*ChargeResponse, error) {
out := new(ChargeResponse)
err := c.cc.Invoke(ctx, "/hipstershop.PaymentService/Charge", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// PaymentServiceServer is the server API for PaymentService service.
type PaymentServiceServer interface {
Charge(context.Context, *ChargeRequest) (*ChargeResponse, error)
}
func RegisterPaymentServiceServer(s *grpc.Server, srv PaymentServiceServer) {
s.RegisterService(&_PaymentService_serviceDesc, srv)
}
func _PaymentService_Charge_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ChargeRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(PaymentServiceServer).Charge(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.PaymentService/Charge",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(PaymentServiceServer).Charge(ctx, req.(*ChargeRequest))
}
return interceptor(ctx, in, info, handler)
}
var _PaymentService_serviceDesc = grpc.ServiceDesc{
ServiceName: "hipstershop.PaymentService",
HandlerType: (*PaymentServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Charge",
Handler: _PaymentService_Charge_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "demo.proto",
}
// EmailServiceClient is the client API for EmailService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type EmailServiceClient interface {
SendOrderConfirmation(ctx context.Context, in *SendOrderConfirmationRequest, opts ...grpc.CallOption) (*Empty, error)
}
type emailServiceClient struct {
cc *grpc.ClientConn
}
func NewEmailServiceClient(cc *grpc.ClientConn) EmailServiceClient {
return &emailServiceClient{cc}
}
func (c *emailServiceClient) SendOrderConfirmation(ctx context.Context, in *SendOrderConfirmationRequest, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/hipstershop.EmailService/SendOrderConfirmation", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// EmailServiceServer is the server API for EmailService service.
type EmailServiceServer interface {
SendOrderConfirmation(context.Context, *SendOrderConfirmationRequest) (*Empty, error)
}
func RegisterEmailServiceServer(s *grpc.Server, srv EmailServiceServer) {
s.RegisterService(&_EmailService_serviceDesc, srv)
}
func _EmailService_SendOrderConfirmation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SendOrderConfirmationRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(EmailServiceServer).SendOrderConfirmation(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.EmailService/SendOrderConfirmation",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(EmailServiceServer).SendOrderConfirmation(ctx, req.(*SendOrderConfirmationRequest))
}
return interceptor(ctx, in, info, handler)
}
var _EmailService_serviceDesc = grpc.ServiceDesc{
ServiceName: "hipstershop.EmailService",
HandlerType: (*EmailServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "SendOrderConfirmation",
Handler: _EmailService_SendOrderConfirmation_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "demo.proto",
}
// CheckoutServiceClient is the client API for CheckoutService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type CheckoutServiceClient interface {
PlaceOrder(ctx context.Context, in *PlaceOrderRequest, opts ...grpc.CallOption) (*PlaceOrderResponse, error)
}
type checkoutServiceClient struct {
cc *grpc.ClientConn
}
func NewCheckoutServiceClient(cc *grpc.ClientConn) CheckoutServiceClient {
return &checkoutServiceClient{cc}
}
func (c *checkoutServiceClient) PlaceOrder(ctx context.Context, in *PlaceOrderRequest, opts ...grpc.CallOption) (*PlaceOrderResponse, error) {
out := new(PlaceOrderResponse)
err := c.cc.Invoke(ctx, "/hipstershop.CheckoutService/PlaceOrder", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// CheckoutServiceServer is the server API for CheckoutService service.
type CheckoutServiceServer interface {
PlaceOrder(context.Context, *PlaceOrderRequest) (*PlaceOrderResponse, error)
}
func RegisterCheckoutServiceServer(s *grpc.Server, srv CheckoutServiceServer) {
s.RegisterService(&_CheckoutService_serviceDesc, srv)
}
func _CheckoutService_PlaceOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PlaceOrderRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CheckoutServiceServer).PlaceOrder(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.CheckoutService/PlaceOrder",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CheckoutServiceServer).PlaceOrder(ctx, req.(*PlaceOrderRequest))
}
return interceptor(ctx, in, info, handler)
}
var _CheckoutService_serviceDesc = grpc.ServiceDesc{
ServiceName: "hipstershop.CheckoutService",
HandlerType: (*CheckoutServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "PlaceOrder",
Handler: _CheckoutService_PlaceOrder_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "demo.proto",
}
// AdServiceClient is the client API for AdService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type AdServiceClient interface {
GetAds(ctx context.Context, in *AdRequest, opts ...grpc.CallOption) (*AdResponse, error)
}
type adServiceClient struct {
cc *grpc.ClientConn
}
func NewAdServiceClient(cc *grpc.ClientConn) AdServiceClient {
return &adServiceClient{cc}
}
func (c *adServiceClient) GetAds(ctx context.Context, in *AdRequest, opts ...grpc.CallOption) (*AdResponse, error) {
out := new(AdResponse)
err := c.cc.Invoke(ctx, "/hipstershop.AdService/GetAds", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// AdServiceServer is the server API for AdService service.
type AdServiceServer interface {
GetAds(context.Context, *AdRequest) (*AdResponse, error)
}
func RegisterAdServiceServer(s *grpc.Server, srv AdServiceServer) {
s.RegisterService(&_AdService_serviceDesc, srv)
}
func _AdService_GetAds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AdRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AdServiceServer).GetAds(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/hipstershop.AdService/GetAds",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AdServiceServer).GetAds(ctx, req.(*AdRequest))
}
return interceptor(ctx, in, info, handler)
}
var _AdService_serviceDesc = grpc.ServiceDesc{
ServiceName: "hipstershop.AdService",
HandlerType: (*AdServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetAds",
Handler: _AdService_GetAds_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "demo.proto",
}
func init() { proto.RegisterFile("demo.proto", fileDescriptor_ca53982754088a9d) }
var fileDescriptor_ca53982754088a9d = []byte{
// 1500 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0xef, 0x72, 0x13, 0xb7,
0x16, 0xcf, 0x26, 0xb1, 0x1d, 0x1f, 0xc7, 0x4e, 0xa2, 0x9b, 0x04, 0xb3, 0x81, 0x10, 0x94, 0x81,
0x0b, 0x17, 0x08, 0x4c, 0xee, 0x9d, 0xe1, 0x03, 0xdc, 0xd2, 0x8c, 0xc9, 0x18, 0x4f, 0xa1, 0xd0,
0x0d, 0xe9, 0xd0, 0xa1, 0x53, 0xcf, 0xb2, 0x12, 0xf1, 0x96, 0xec, 0x6a, 0x91, 0xb4, 0x19, 0xcc,
0xc7, 0xf6, 0x01, 0xfa, 0x1e, 0x7d, 0x81, 0xce, 0xf4, 0x11, 0xfa, 0xbd, 0xaf, 0xd0, 0xe7, 0xe8,
0x48, 0xbb, 0xda, 0x7f, 0xb1, 0x13, 0xf8, 0xd2, 0x6f, 0xab, 0xa3, 0x9f, 0xce, 0xf9, 0xe9, 0xe8,
0xfc, 0xb3, 0x01, 0x08, 0x0d, 0xd8, 0x4e, 0xc4, 0x99, 0x64, 0xa8, 0x35, 0xf2, 0x23, 0x21, 0x29,
0x17, 0x23, 0x16, 0xe1, 0x7d, 0x58, 0xe8, 0xb9, 0x5c, 0x0e, 0x24, 0x0d, 0xd0, 0x65, 0x80, 0x88,
0x33, 0x12, 0x7b, 0x72, 0xe8, 0x93, 0xae, 0xb5, 0x65, 0xdd, 0x68, 0x3a, 0xcd, 0x54, 0x32, 0x20,
0xc8, 0x86, 0x85, 0xf7, 0xb1, 0x1b, 0x4a, 0x5f, 0x8e, 0xbb, 0xb3, 0x5b, 0xd6, 0x8d, 0x9a, 0x93,
0xad, 0xf1, 0x4b, 0xe8, 0xec, 0x11, 0xa2, 0xb4, 0x38, 0xf4, 0x7d, 0x4c, 0x85, 0x44, 0x17, 0xa0,
0x11, 0x0b, 0xca, 0x73, 0x4d, 0x75, 0xb5, 0x1c, 0x10, 0x74, 0x13, 0xe6, 0x7d, 0x49, 0x03, 0xad,
0xa2, 0xb5, 0xbb, 0xb6, 0x53, 0x60, 0xb3, 0x63, 0xa8, 0x38, 0x1a, 0x82, 0x6f, 0xc1, 0xf2, 0x7e,
0x10, 0xc9, 0xb1, 0x12, 0x9f, 0xa7, 0x17, 0xdf, 0x84, 0x4e, 0x9f, 0xca, 0x4f, 0x82, 0x3e, 0x85,
0x79, 0x85, 0x9b, 0xce, 0xf1, 0x16, 0xd4, 0x14, 0x01, 0xd1, 0x9d, 0xdd, 0x9a, 0x9b, 0x4e, 0x32,
0xc1, 0xe0, 0x06, 0xd4, 0x34, 0x4b, 0xfc, 0x2d, 0xd8, 0x4f, 0x7d, 0x21, 0x1d, 0xea, 0xb1, 0x20,
0xa0, 0x21, 0x71, 0xa5, 0xcf, 0x42, 0x71, 0xae, 0x43, 0xae, 0x40, 0x2b, 0x77, 0x7b, 0x62, 0xb2,
0xe9, 0x40, 0xe6, 0x77, 0x81, 0xbf, 0x80, 0x8d, 0x89, 0x7a, 0x45, 0xc4, 0x42, 0x41, 0xab, 0xe7,
0xad, 0x53, 0xe7, 0x7f, 0xb7, 0xa0, 0xf1, 0x22, 0x59, 0xa2, 0x0e, 0xcc, 0x66, 0x04, 0x66, 0x7d,
0x82, 0x10, 0xcc, 0x87, 0x6e, 0x40, 0xf5, 0x6b, 0x34, 0x1d, 0xfd, 0x8d, 0xb6, 0xa0, 0x45, 0xa8,
0xf0, 0xb8, 0x1f, 0x29, 0x43, 0xdd, 0x39, 0xbd, 0x55, 0x14, 0xa1, 0x2e, 0x34, 0x22, 0xdf, 0x93,
0x31, 0xa7, 0xdd, 0x79, 0xbd, 0x6b, 0x96, 0xe8, 0x2e, 0x34, 0x23, 0xee, 0x7b, 0x74, 0x18, 0x0b,
0xd2, 0xad, 0xe9, 0x27, 0x46, 0x25, 0xef, 0x3d, 0x63, 0x21, 0x1d, 0x3b, 0x0b, 0x1a, 0x74, 0x28,
0x08, 0xda, 0x04, 0xf0, 0x5c, 0x49, 0x8f, 0x18, 0xf7, 0xa9, 0xe8, 0xd6, 0x13, 0xf2, 0xb9, 0x04,
0x3f, 0x81, 0x55, 0x75, 0xf9, 0x94, 0x7f, 0x7e, 0xeb, 0x7b, 0xb0, 0x90, 0x5e, 0x31, 0xb9, 0x72,
0x6b, 0x77, 0xb5, 0x64, 0x27, 0x3d, 0xe0, 0x64, 0x28, 0xbc, 0x0d, 0x2b, 0x7d, 0x6a, 0x14, 0x99,
0x57, 0xa9, 0xf8, 0x03, 0xdf, 0x81, 0xb5, 0x03, 0xea, 0x72, 0x6f, 0x94, 0x1b, 0x4c, 0x80, 0xab,
0x50, 0x7b, 0x1f, 0x53, 0x3e, 0x4e, 0xb1, 0xc9, 0x02, 0x3f, 0x81, 0xf5, 0x2a, 0x3c, 0xe5, 0xb7,
0x03, 0x0d, 0x4e, 0x45, 0x7c, 0x7c, 0x0e, 0x3d, 0x03, 0xc2, 0x21, 0x2c, 0xf5, 0xa9, 0xfc, 0x26,
0x66, 0x92, 0x1a, 0x93, 0x3b, 0xd0, 0x70, 0x09, 0xe1, 0x54, 0x08, 0x6d, 0xb4, 0xaa, 0x62, 0x2f,
0xd9, 0x73, 0x0c, 0xe8, 0xf3, 0xa2, 0x76, 0x0f, 0x96, 0x73, 0x7b, 0x29, 0xe7, 0x3b, 0xb0, 0xe0,
0x31, 0x21, 0xf5, 0xdb, 0x59, 0x53, 0xdf, 0xae, 0xa1, 0x30, 0x87, 0x82, 0x60, 0x06, 0xcb, 0x07,
0x23, 0x3f, 0x7a, 0xce, 0x09, 0xe5, 0xff, 0x08, 0xe7, 0xff, 0xc1, 0x4a, 0xc1, 0x60, 0x1e, 0xfe,
0x92, 0xbb, 0xde, 0x3b, 0x3f, 0x3c, 0xca, 0x73, 0x0b, 0x8c, 0x68, 0x40, 0xf0, 0x2f, 0x16, 0x34,
0x52, 0xbb, 0xe8, 0x1a, 0x74, 0x84, 0xe4, 0x94, 0xca, 0x61, 0x91, 0x65, 0xd3, 0x69, 0x27, 0x52,
0x03, 0x43, 0x30, 0xef, 0x99, 0x32, 0xd7, 0x74, 0xf4, 0xb7, 0x0a, 0x00, 0x21, 0x5d, 0x49, 0xd3,
0x7c, 0x48, 0x16, 0x2a, 0x13, 0x3c, 0x16, 0x87, 0x92, 0x8f, 0x4d, 0x26, 0xa4, 0x4b, 0x74, 0x11,
0x16, 0x3e, 0xfa, 0xd1, 0xd0, 0x63, 0x84, 0xea, 0x44, 0xa8, 0x39, 0x8d, 0x8f, 0x7e, 0xd4, 0x63,
0x84, 0xe2, 0x57, 0x50, 0xd3, 0xae, 0x44, 0xdb, 0xd0, 0xf6, 0x62, 0xce, 0x69, 0xe8, 0x8d, 0x13,
0x60, 0xc2, 0x66, 0xd1, 0x08, 0x15, 0x5a, 0x19, 0x8e, 0x43, 0x5f, 0x0a, 0xcd, 0x66, 0xce, 0x49,
0x16, 0x4a, 0x1a, 0xba, 0x21, 0x13, 0x9a, 0x4e, 0xcd, 0x49, 0x16, 0xb8, 0x0f, 0x9b, 0x7d, 0x2a,
0x0f, 0xe2, 0x28, 0x62, 0x5c, 0x52, 0xd2, 0x4b, 0xf4, 0xf8, 0x34, 0x8f, 0xcb, 0x6b, 0xd0, 0x29,
0x99, 0x34, 0x05, 0xa3, 0x5d, 0xb4, 0x29, 0xf0, 0xf7, 0x70, 0xb1, 0x97, 0x09, 0xc2, 0x13, 0xca,
0x85, 0xcf, 0x42, 0xf3, 0xc8, 0xd7, 0x61, 0xfe, 0x2d, 0x67, 0xc1, 0x19, 0x31, 0xa2, 0xf7, 0x55,
0xc9, 0x93, 0x2c, 0xb9, 0x58, 0xe2, 0xc9, 0xba, 0x64, 0xda, 0x01, 0x7f, 0x59, 0xd0, 0xe9, 0x71,
0x4a, 0x7c, 0x55, 0xaf, 0xc9, 0x20, 0x7c, 0xcb, 0xd0, 0x6d, 0x40, 0x9e, 0x96, 0x0c, 0x3d, 0x97,
0x93, 0x61, 0x18, 0x07, 0x6f, 0x28, 0x4f, 0xfd, 0xb1, 0xec, 0x65, 0xd8, 0xaf, 0xb5, 0x1c, 0x5d,
0x87, 0xa5, 0x22, 0xda, 0x3b, 0x39, 0x49, 0x5b, 0x52, 0x3b, 0x87, 0xf6, 0x4e, 0x4e, 0xd0, 0xff,
0x61, 0xa3, 0x88, 0xa3, 0x1f, 0x22, 0x9f, 0xeb, 0xf2, 0x39, 0x1c, 0x53, 0x97, 0xa7, 0xbe, 0xeb,
0xe6, 0x67, 0xf6, 0x33, 0xc0, 0x77, 0xd4, 0xe5, 0xe8, 0x11, 0x5c, 0x9a, 0x72, 0x3c, 0x60, 0xa1,
0x1c, 0xe9, 0x27, 0xaf, 0x39, 0x17, 0x27, 0x9d, 0x7f, 0xa6, 0x00, 0x78, 0x0c, 0xed, 0xde, 0xc8,
0xe5, 0x47, 0x59, 0x4e, 0xff, 0x07, 0xea, 0x6e, 0xa0, 0x22, 0xe4, 0x0c, 0xe7, 0xa5, 0x08, 0xf4,
0x10, 0x5a, 0x05, 0xeb, 0x69, 0xc3, 0xdc, 0x28, 0x67, 0x48, 0xc9, 0x89, 0x0e, 0xe4, 0x4c, 0xf0,
0x7d, 0xe8, 0x18, 0xd3, 0xf9, 0xd3, 0x4b, 0xee, 0x86, 0xc2, 0xf5, 0xf4, 0x15, 0xb2, 0x64, 0x69,
0x17, 0xa4, 0x03, 0x82, 0x7f, 0x80, 0xa6, 0xce, 0x30, 0x3d, 0x13, 0x98, 0x6e, 0x6d, 0x9d, 0xdb,
0xad, 0x55, 0x54, 0xa8, 0xca, 0x90, 0xf2, 0x9c, 0x18, 0x15, 0x6a, 0x1f, 0xff, 0x34, 0x0b, 0x2d,
0x93, 0xc2, 0xf1, 0xb1, 0x54, 0x89, 0xc2, 0xd4, 0x32, 0x27, 0xd4, 0xd0, 0xeb, 0x01, 0x41, 0xf7,
0x60, 0x55, 0x8c, 0xfc, 0x28, 0x52, 0xb9, 0x5d, 0x4c, 0xf2, 0x24, 0x9a, 0x90, 0xd9, 0x7b, 0x99,
0x25, 0x3b, 0xba, 0x0f, 0xed, 0xec, 0x84, 0x66, 0x33, 0x37, 0x95, 0xcd, 0xa2, 0x01, 0xf6, 0x98,
0x90, 0xe8, 0x11, 0x2c, 0x67, 0x07, 0x4d, 0x6d, 0x98, 0x3f, 0xa3, 0x82, 0x2d, 0x19, 0xb4, 0xa9,
0x19, 0xb7, 0x4d, 0x25, 0xab, 0xe9, 0x4a, 0xb6, 0x5e, 0x3a, 0x95, 0x39, 0xd4, 0x94, 0x32, 0x02,
0x97, 0x0e, 0x68, 0x48, 0xb4, 0xbc, 0xc7, 0xc2, 0xb7, 0x3e, 0x0f, 0x74, 0xd8, 0x14, 0xda, 0x0d,
0x0d, 0x5c, 0xff, 0xd8, 0xb4, 0x1b, 0xbd, 0x40, 0x3b, 0x50, 0xd3, 0xae, 0x49, 0x7d, 0xdc, 0x3d,
0x6d, 0x23, 0xf1, 0xa9, 0x93, 0xc0, 0xf0, 0x9f, 0x16, 0xac, 0xbc, 0x38, 0x76, 0x3d, 0x5a, 0xaa,
0xd1, 0x53, 0x27, 0x91, 0x6d, 0x68, 0xeb, 0x0d, 0x53, 0x0a, 0x52, 0x3f, 0x2f, 0x2a, 0xa1, 0xa9,
0x06, 0xc5, 0x0a, 0x3f, 0xf7, 0x29, 0x15, 0x3e, 0xbb, 0x49, 0xad, 0x78, 0x93, 0x4a, 0x6c, 0xd7,
0x3f, 0x2f, 0xb6, 0x1f, 0x03, 0x2a, 0x5e, 0x2b, 0x6b, 0xb9, 0xa9, 0x77, 0xac, 0x4f, 0xf3, 0xce,
0x0e, 0x34, 0xf7, 0x88, 0x71, 0xca, 0x55, 0x58, 0xf4, 0x58, 0x28, 0xe9, 0x07, 0x39, 0x7c, 0x47,
0xc7, 0xa6, 0x2a, 0xb6, 0x52, 0xd9, 0x57, 0x74, 0x2c, 0xf0, 0x5d, 0x00, 0x85, 0x4f, 0xad, 0x5d,
0x85, 0x39, 0x97, 0x98, 0xe6, 0xbe, 0x54, 0xf1, 0x81, 0xa3, 0xf6, 0xf0, 0x03, 0x98, 0xdd, 0x23,
0x4a, 0xb3, 0x62, 0xce, 0xa9, 0x27, 0x87, 0x31, 0x37, 0x2f, 0xda, 0x32, 0xb2, 0x43, 0x7e, 0xac,
0xfa, 0x8d, 0xb2, 0x62, 0xfa, 0x8d, 0xfa, 0xde, 0xfd, 0xc3, 0x82, 0x96, 0xca, 0xb0, 0x03, 0xca,
0x4f, 0x7c, 0x8f, 0xa2, 0x87, 0xba, 0x8b, 0xe9, 0xa4, 0xdc, 0xa8, 0x7a, 0xbc, 0x30, 0x78, 0xdb,
0xe5, 0x50, 0x4f, 0x26, 0xd3, 0x19, 0xf4, 0x00, 0x1a, 0xe9, 0x74, 0x5c, 0x39, 0x5d, 0x9e, 0x99,
0xed, 0x95, 0x53, 0x19, 0x8e, 0x67, 0xd0, 0x97, 0xd0, 0xcc, 0xe6, 0x70, 0x74, 0xf9, 0xb4, 0xfe,
0xa2, 0x82, 0x89, 0xe6, 0x77, 0x7f, 0xb6, 0x60, 0xad, 0x3c, 0xbf, 0x9a, 0x6b, 0xfd, 0x08, 0xff,
0x9a, 0x30, 0xdc, 0xa2, 0x7f, 0x97, 0xd4, 0x4c, 0x1f, 0xab, 0xed, 0x1b, 0xe7, 0x03, 0x93, 0x07,
0x53, 0x2c, 0x66, 0x61, 0x2d, 0x1d, 0xbc, 0x7a, 0xae, 0x74, 0x8f, 0xd9, 0x91, 0x61, 0xd1, 0x87,
0xc5, 0xe2, 0x94, 0x89, 0x26, 0xdc, 0xc2, 0xbe, 0x7a, 0xca, 0x52, 0x75, 0xe8, 0xc3, 0x33, 0xe8,
0x31, 0x40, 0x3e, 0x64, 0xa2, 0xcd, 0xaa, 0xab, 0xcb, 0xd3, 0xa7, 0x3d, 0x71, 0x26, 0xc4, 0x33,
0xe8, 0x35, 0x74, 0xca, 0x63, 0x25, 0xc2, 0x25, 0xe4, 0xc4, 0x11, 0xd5, 0xde, 0x3e, 0x13, 0x93,
0x79, 0xe1, 0x57, 0x0b, 0x96, 0x0e, 0xd2, 0xe2, 0x65, 0xee, 0x3f, 0x80, 0x05, 0x33, 0x0d, 0xa2,
0x4b, 0x55, 0xd2, 0xc5, 0xa1, 0xd4, 0xbe, 0x3c, 0x65, 0x37, 0xf3, 0xc0, 0x53, 0x68, 0x66, 0x43,
0x5a, 0x25, 0x58, 0xaa, 0xd3, 0xa2, 0xbd, 0x39, 0x6d, 0x3b, 0x23, 0xfb, 0x9b, 0x05, 0x4b, 0xa6,
0xf4, 0x18, 0xb2, 0xaf, 0x61, 0x7d, 0xf2, 0x90, 0x33, 0xf1, 0xd9, 0x6e, 0x55, 0x09, 0x9f, 0x31,
0x1d, 0xe1, 0x19, 0xd4, 0x87, 0x46, 0x32, 0xf0, 0x48, 0x74, 0xbd, 0x9c, 0x0b, 0xd3, 0xc6, 0x21,
0x7b, 0x42, 0x73, 0xc1, 0x33, 0xbb, 0x87, 0xd0, 0x79, 0xe1, 0x8e, 0x03, 0x1a, 0x66, 0x19, 0xdc,
0x83, 0x7a, 0xd2, 0x91, 0x91, 0x5d, 0xd6, 0x5c, 0x9c, 0x10, 0xec, 0x8d, 0x89, 0x7b, 0x99, 0x43,
0x46, 0xb0, 0xb8, 0xaf, 0x2a, 0xa8, 0x51, 0xfa, 0x4a, 0xfd, 0x60, 0x99, 0xd0, 0x48, 0xd0, 0xcd,
0x4a, 0x34, 0x4c, 0x6f, 0x36, 0x53, 0x72, 0xf6, 0x0d, 0x2c, 0xf5, 0x46, 0xd4, 0x7b, 0xc7, 0xe2,
0xec, 0x06, 0xcf, 0x01, 0xf2, 0xba, 0x5b, 0x89, 0xee, 0x53, 0x7d, 0xc6, 0xbe, 0x32, 0x75, 0x3f,
0xbb, 0xcd, 0x13, 0x55, 0x82, 0x8d, 0xf6, 0x07, 0x50, 0xef, 0xab, 0x19, 0x5c, 0xa0, 0xf5, 0x6a,
0x39, 0x4d, 0x35, 0x5e, 0x38, 0x25, 0x37, 0x9a, 0xde, 0xd4, 0xf5, 0x9f, 0x1b, 0xff, 0xfd, 0x3b,
0x00, 0x00, 0xff, 0xff, 0xb2, 0xa0, 0x6e, 0x6c, 0xea, 0x10, 0x00, 0x00,
}
// Copyright 2018 Google LLC
//
// 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 (
"context"
"fmt"
"html/template"
"math/rand"
"net/http"
"os"
"strconv"
"strings"
"time"
"github.com/gorilla/mux"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
pb "github.com/GoogleCloudPlatform/microservices-demo/src/frontend/genproto"
"github.com/GoogleCloudPlatform/microservices-demo/src/frontend/money"
)
type platformDetails struct {
css string
provider string
}
var (
templates = template.Must(template.New("").
Funcs(template.FuncMap{
"renderMoney": renderMoney,
}).ParseGlob("templates/*.html"))
plat platformDetails
)
func (fe *frontendServer) homeHandler(w http.ResponseWriter, r *http.Request) {
log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)
log.WithField("currency", currentCurrency(r)).Info("home")
currencies, err := fe.getCurrencies(r.Context())
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError)
return
}
products, err := fe.getProducts(r.Context())
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve products"), http.StatusInternalServerError)
return
}
cart, err := fe.getCart(r.Context(), sessionID(r))
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve cart"), http.StatusInternalServerError)
return
}
type productView struct {
Item *pb.Product
Price *pb.Money
}
ps := make([]productView, len(products))
for i, p := range products {
price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
if err != nil {
renderHTTPError(log, r, w, errors.Wrapf(err, "failed to do currency conversion for product %s", p.GetId()), http.StatusInternalServerError)
return
}
ps[i] = productView{p, price}
}
//get env and render correct platform banner.
var env = os.Getenv("ENV_PLATFORM")
plat = platformDetails{}
plat.setPlatformDetails(strings.ToLower(env))
if err := templates.ExecuteTemplate(w, "home", map[string]interface{}{
"session_id": sessionID(r),
"request_id": r.Context().Value(ctxKeyRequestID{}),
"user_currency": currentCurrency(r),
"show_currency": true,
"currencies": currencies,
"products": ps,
"cart_size": cartSize(cart),
"banner_color": os.Getenv("BANNER_COLOR"), // illustrates canary deployments
"ad": fe.chooseAd(r.Context(), []string{}, log),
"platform_css": plat.css,
"platform_name": plat.provider,
}); err != nil {
log.Error(err)
}
}
func (plat *platformDetails) setPlatformDetails(env string) {
if env == "aws" {
plat.provider = "AWS"
plat.css = "aws-platform"
} else if env == "onprem" {
plat.provider = "On-Premises"
plat.css = "onprem-platform"
} else if env == "azure" {
plat.provider = "Azure"
plat.css = "azure-platform"
} else {
plat.provider = "Google Cloud"
plat.css = "gcp-platform"
}
}
func (fe *frontendServer) productHandler(w http.ResponseWriter, r *http.Request) {
log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)
id := mux.Vars(r)["id"]
if id == "" {
renderHTTPError(log, r, w, errors.New("product id not specified"), http.StatusBadRequest)
return
}
log.WithField("id", id).WithField("currency", currentCurrency(r)).
Debug("serving product page")
p, err := fe.getProduct(r.Context(), id)
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve product"), http.StatusInternalServerError)
return
}
currencies, err := fe.getCurrencies(r.Context())
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError)
return
}
cart, err := fe.getCart(r.Context(), sessionID(r))
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve cart"), http.StatusInternalServerError)
return
}
price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "failed to convert currency"), http.StatusInternalServerError)
return
}
recommendations, err := fe.getRecommendations(r.Context(), sessionID(r), []string{id})
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "failed to get product recommendations"), http.StatusInternalServerError)
return
}
product := struct {
Item *pb.Product
Price *pb.Money
}{p, price}
if err := templates.ExecuteTemplate(w, "product", map[string]interface{}{
"session_id": sessionID(r),
"request_id": r.Context().Value(ctxKeyRequestID{}),
"ad": fe.chooseAd(r.Context(), p.Categories, log),
"user_currency": currentCurrency(r),
"show_currency": true,
"currencies": currencies,
"product": product,
"recommendations": recommendations,
"cart_size": cartSize(cart),
"platform_css": plat.css,
"platform_name": plat.provider,
}); err != nil {
log.Println(err)
}
}
func (fe *frontendServer) addToCartHandler(w http.ResponseWriter, r *http.Request) {
log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)
quantity, _ := strconv.ParseUint(r.FormValue("quantity"), 10, 32)
productID := r.FormValue("product_id")
if productID == "" || quantity == 0 {
renderHTTPError(log, r, w, errors.New("invalid form input"), http.StatusBadRequest)
return
}
log.WithField("product", productID).WithField("quantity", quantity).Debug("adding to cart")
p, err := fe.getProduct(r.Context(), productID)
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve product"), http.StatusInternalServerError)
return
}
if err := fe.insertCart(r.Context(), sessionID(r), p.GetId(), int32(quantity)); err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "failed to add to cart"), http.StatusInternalServerError)
return
}
w.Header().Set("location", "/cart")
w.WriteHeader(http.StatusFound)
}
func (fe *frontendServer) emptyCartHandler(w http.ResponseWriter, r *http.Request) {
log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)
log.Debug("emptying cart")
if err := fe.emptyCart(r.Context(), sessionID(r)); err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "failed to empty cart"), http.StatusInternalServerError)
return
}
w.Header().Set("location", "/")
w.WriteHeader(http.StatusFound)
}
func (fe *frontendServer) viewCartHandler(w http.ResponseWriter, r *http.Request) {
log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)
log.Debug("view user cart")
currencies, err := fe.getCurrencies(r.Context())
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError)
return
}
cart, err := fe.getCart(r.Context(), sessionID(r))
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve cart"), http.StatusInternalServerError)
return
}
recommendations, err := fe.getRecommendations(r.Context(), sessionID(r), cartIDs(cart))
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "failed to get product recommendations"), http.StatusInternalServerError)
return
}
shippingCost, err := fe.getShippingQuote(r.Context(), cart, currentCurrency(r))
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "failed to get shipping quote"), http.StatusInternalServerError)
return
}
type cartItemView struct {
Item *pb.Product
Quantity int32
Price *pb.Money
}
items := make([]cartItemView, len(cart))
totalPrice := pb.Money{CurrencyCode: currentCurrency(r)}
for i, item := range cart {
p, err := fe.getProduct(r.Context(), item.GetProductId())
if err != nil {
renderHTTPError(log, r, w, errors.Wrapf(err, "could not retrieve product #%s", item.GetProductId()), http.StatusInternalServerError)
return
}
price, err := fe.convertCurrency(r.Context(), p.GetPriceUsd(), currentCurrency(r))
if err != nil {
renderHTTPError(log, r, w, errors.Wrapf(err, "could not convert currency for product #%s", item.GetProductId()), http.StatusInternalServerError)
return
}
multPrice := money.MultiplySlow(*price, uint32(item.GetQuantity()))
items[i] = cartItemView{
Item: p,
Quantity: item.GetQuantity(),
Price: &multPrice}
totalPrice = money.Must(money.Sum(totalPrice, multPrice))
}
totalPrice = money.Must(money.Sum(totalPrice, *shippingCost))
year := time.Now().Year()
if err := templates.ExecuteTemplate(w, "cart", map[string]interface{}{
"session_id": sessionID(r),
"request_id": r.Context().Value(ctxKeyRequestID{}),
"user_currency": currentCurrency(r),
"currencies": currencies,
"recommendations": recommendations,
"cart_size": cartSize(cart),
"shipping_cost": shippingCost,
"show_currency": true,
"total_cost": totalPrice,
"items": items,
"expiration_years": []int{year, year + 1, year + 2, year + 3, year + 4},
"platform_css": plat.css,
"platform_name": plat.provider,
}); err != nil {
log.Println(err)
}
}
func (fe *frontendServer) placeOrderHandler(w http.ResponseWriter, r *http.Request) {
log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)
log.Debug("placing order")
var (
email = r.FormValue("email")
streetAddress = r.FormValue("street_address")
zipCode, _ = strconv.ParseInt(r.FormValue("zip_code"), 10, 32)
city = r.FormValue("city")
state = r.FormValue("state")
country = r.FormValue("country")
ccNumber = r.FormValue("credit_card_number")
ccMonth, _ = strconv.ParseInt(r.FormValue("credit_card_expiration_month"), 10, 32)
ccYear, _ = strconv.ParseInt(r.FormValue("credit_card_expiration_year"), 10, 32)
ccCVV, _ = strconv.ParseInt(r.FormValue("credit_card_cvv"), 10, 32)
)
order, err := pb.NewCheckoutServiceClient(fe.checkoutSvcConn).
PlaceOrder(r.Context(), &pb.PlaceOrderRequest{
Email: email,
CreditCard: &pb.CreditCardInfo{
CreditCardNumber: ccNumber,
CreditCardExpirationMonth: int32(ccMonth),
CreditCardExpirationYear: int32(ccYear),
CreditCardCvv: int32(ccCVV)},
UserId: sessionID(r),
UserCurrency: currentCurrency(r),
Address: &pb.Address{
StreetAddress: streetAddress,
City: city,
State: state,
ZipCode: int32(zipCode),
Country: country},
})
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "failed to complete the order"), http.StatusInternalServerError)
return
}
log.WithField("order", order.GetOrder().GetOrderId()).Info("order placed")
order.GetOrder().GetItems()
recommendations, _ := fe.getRecommendations(r.Context(), sessionID(r), nil)
totalPaid := *order.GetOrder().GetShippingCost()
for _, v := range order.GetOrder().GetItems() {
totalPaid = money.Must(money.Sum(totalPaid, *v.GetCost()))
}
currencies, err := fe.getCurrencies(r.Context())
if err != nil {
renderHTTPError(log, r, w, errors.Wrap(err, "could not retrieve currencies"), http.StatusInternalServerError)
return
}
if err := templates.ExecuteTemplate(w, "order", map[string]interface{}{
"session_id": sessionID(r),
"request_id": r.Context().Value(ctxKeyRequestID{}),
"user_currency": currentCurrency(r),
"show_currency": false,
"currencies": currencies,
"order": order.GetOrder(),
"total_paid": &totalPaid,
"recommendations": recommendations,
"platform_css": plat.css,
"platform_name": plat.provider,
}); err != nil {
log.Println(err)
}
}
func (fe *frontendServer) logoutHandler(w http.ResponseWriter, r *http.Request) {
log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)
log.Debug("logging out")
for _, c := range r.Cookies() {
c.Expires = time.Now().Add(-time.Hour * 24 * 365)
c.MaxAge = -1
http.SetCookie(w, c)
}
w.Header().Set("Location", "/")
w.WriteHeader(http.StatusFound)
}
func (fe *frontendServer) setCurrencyHandler(w http.ResponseWriter, r *http.Request) {
log := r.Context().Value(ctxKeyLog{}).(logrus.FieldLogger)
cur := r.FormValue("currency_code")
log.WithField("curr.new", cur).WithField("curr.old", currentCurrency(r)).
Debug("setting currency")
if cur != "" {
http.SetCookie(w, &http.Cookie{
Name: cookieCurrency,
Value: cur,
MaxAge: cookieMaxAge,
})
}
referer := r.Header.Get("referer")
if referer == "" {
referer = "/"
}
w.Header().Set("Location", referer)
w.WriteHeader(http.StatusFound)
}
// chooseAd queries for advertisements available and randomly chooses one, if
// available. It ignores the error retrieving the ad since it is not critical.
func (fe *frontendServer) chooseAd(ctx context.Context, ctxKeys []string, log logrus.FieldLogger) *pb.Ad {
ads, err := fe.getAd(ctx, ctxKeys)
if err != nil {
log.WithField("error", err).Warn("failed to retrieve ads")
return nil
}
return ads[rand.Intn(len(ads))]
}
func renderHTTPError(log logrus.FieldLogger, r *http.Request, w http.ResponseWriter, err error, code int) {
log.WithField("error", err).Error("request error")
errMsg := fmt.Sprintf("%+v", err)
w.WriteHeader(code)
if templateErr := templates.ExecuteTemplate(w, "error", map[string]interface{}{
"session_id": sessionID(r),
"request_id": r.Context().Value(ctxKeyRequestID{}),
"error": errMsg,
"status_code": code,
"status": http.StatusText(code),
}); templateErr != nil {
log.Println(templateErr)
}
}
func currentCurrency(r *http.Request) string {
c, _ := r.Cookie(cookieCurrency)
if c != nil {
return c.Value
}
return defaultCurrency
}
func sessionID(r *http.Request) string {
v := r.Context().Value(ctxKeySessionID{})
if v != nil {
return v.(string)
}
return ""
}
func cartIDs(c []*pb.CartItem) []string {
out := make([]string, len(c))
for i, v := range c {
out[i] = v.GetProductId()
}
return out
}
// get total # of items in cart
func cartSize(c []*pb.CartItem) int {
cartSize := 0
for _, item := range c {
cartSize += int(item.GetQuantity())
}
return cartSize
}
func renderMoney(money pb.Money) string {
return fmt.Sprintf("%s %d.%02d", money.GetCurrencyCode(), money.GetUnits(), money.GetNanos()/10000000)
}
// Copyright 2018 Google LLC
//
// 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 (
"context"
"fmt"
"net/http"
"os"
"time"
"cloud.google.com/go/profiler"
"contrib.go.opencensus.io/exporter/jaeger"
"contrib.go.opencensus.io/exporter/stackdriver"
"github.com/gorilla/mux"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"go.opencensus.io/plugin/ocgrpc"
"go.opencensus.io/plugin/ochttp"
"go.opencensus.io/plugin/ochttp/propagation/b3"
"go.opencensus.io/stats/view"
"go.opencensus.io/trace"
"google.golang.org/grpc"
)
const (
port = "8080"
defaultCurrency = "USD"
cookieMaxAge = 60 * 60 * 48
cookiePrefix = "shop_"
cookieSessionID = cookiePrefix + "session-id"
cookieCurrency = cookiePrefix + "currency"
)
var (
whitelistedCurrencies = map[string]bool{
"USD": true,
"EUR": true,
"CAD": true,
"JPY": true,
"GBP": true,
"TRY": true}
)
type ctxKeySessionID struct{}
type frontendServer struct {
productCatalogSvcAddr string
productCatalogSvcConn *grpc.ClientConn
currencySvcAddr string
currencySvcConn *grpc.ClientConn
cartSvcAddr string
cartSvcConn *grpc.ClientConn
recommendationSvcAddr string
recommendationSvcConn *grpc.ClientConn
checkoutSvcAddr string
checkoutSvcConn *grpc.ClientConn
shippingSvcAddr string
shippingSvcConn *grpc.ClientConn
adSvcAddr string
adSvcConn *grpc.ClientConn
}
func main() {
ctx := context.Background()
log := logrus.New()
log.Level = logrus.DebugLevel
log.Formatter = &logrus.JSONFormatter{
FieldMap: logrus.FieldMap{
logrus.FieldKeyTime: "timestamp",
logrus.FieldKeyLevel: "severity",
logrus.FieldKeyMsg: "message",
},
TimestampFormat: time.RFC3339Nano,
}
log.Out = os.Stdout
if os.Getenv("DISABLE_TRACING") == "" {
log.Info("Tracing enabled.")
go initTracing(log)
} else {
log.Info("Tracing disabled.")
}
if os.Getenv("DISABLE_PROFILER") == "" {
log.Info("Profiling enabled.")
go initProfiling(log, "frontend", "1.0.0")
} else {
log.Info("Profiling disabled.")
}
srvPort := port
if os.Getenv("PORT") != "" {
srvPort = os.Getenv("PORT")
}
addr := os.Getenv("LISTEN_ADDR")
svc := new(frontendServer)
mustMapEnv(&svc.productCatalogSvcAddr, "PRODUCT_CATALOG_SERVICE_ADDR")
mustMapEnv(&svc.currencySvcAddr, "CURRENCY_SERVICE_ADDR")
mustMapEnv(&svc.cartSvcAddr, "CART_SERVICE_ADDR")
mustMapEnv(&svc.recommendationSvcAddr, "RECOMMENDATION_SERVICE_ADDR")
mustMapEnv(&svc.checkoutSvcAddr, "CHECKOUT_SERVICE_ADDR")
mustMapEnv(&svc.shippingSvcAddr, "SHIPPING_SERVICE_ADDR")
mustMapEnv(&svc.adSvcAddr, "AD_SERVICE_ADDR")
mustConnGRPC(ctx, &svc.currencySvcConn, svc.currencySvcAddr)
mustConnGRPC(ctx, &svc.productCatalogSvcConn, svc.productCatalogSvcAddr)
mustConnGRPC(ctx, &svc.cartSvcConn, svc.cartSvcAddr)
mustConnGRPC(ctx, &svc.recommendationSvcConn, svc.recommendationSvcAddr)
mustConnGRPC(ctx, &svc.shippingSvcConn, svc.shippingSvcAddr)
mustConnGRPC(ctx, &svc.checkoutSvcConn, svc.checkoutSvcAddr)
mustConnGRPC(ctx, &svc.adSvcConn, svc.adSvcAddr)
r := mux.NewRouter()
r.HandleFunc("/", svc.homeHandler).Methods(http.MethodGet, http.MethodHead)
r.HandleFunc("/product/{id}", svc.productHandler).Methods(http.MethodGet, http.MethodHead)
r.HandleFunc("/cart", svc.viewCartHandler).Methods(http.MethodGet, http.MethodHead)
r.HandleFunc("/cart", svc.addToCartHandler).Methods(http.MethodPost)
r.HandleFunc("/cart/empty", svc.emptyCartHandler).Methods(http.MethodPost)
r.HandleFunc("/setCurrency", svc.setCurrencyHandler).Methods(http.MethodPost)
r.HandleFunc("/logout", svc.logoutHandler).Methods(http.MethodGet)
r.HandleFunc("/cart/checkout", svc.placeOrderHandler).Methods(http.MethodPost)
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./static/"))))
r.HandleFunc("/robots.txt", func(w http.ResponseWriter, _ *http.Request) { fmt.Fprint(w, "User-agent: *\nDisallow: /") })
r.HandleFunc("/_healthz", func(w http.ResponseWriter, _ *http.Request) { fmt.Fprint(w, "ok") })
var handler http.Handler = r
handler = &logHandler{log: log, next: handler} // add logging
handler = ensureSessionID(handler) // add session ID
handler = &ochttp.Handler{ // add opencensus instrumentation
Handler: handler,
Propagation: &b3.HTTPFormat{}}
log.Infof("starting server on " + addr + ":" + srvPort)
log.Fatal(http.ListenAndServe(addr+":"+srvPort, handler))
}
func initJaegerTracing(log logrus.FieldLogger) {
svcAddr := os.Getenv("JAEGER_SERVICE_ADDR")
if svcAddr == "" {
log.Info("jaeger initialization disabled.")
return
}
// Register the Jaeger exporter to be able to retrieve
// the collected spans.
exporter, err := jaeger.NewExporter(jaeger.Options{
Endpoint: fmt.Sprintf("http://%s", svcAddr),
Process: jaeger.Process{
ServiceName: "frontend",
},
})
if err != nil {
log.Fatal(err)
}
trace.RegisterExporter(exporter)
log.Info("jaeger initialization completed.")
}
func initStats(log logrus.FieldLogger, exporter *stackdriver.Exporter) {
view.SetReportingPeriod(60 * time.Second)
view.RegisterExporter(exporter)
if err := view.Register(ochttp.DefaultServerViews...); err != nil {
log.Warn("Error registering http default server views")
} else {
log.Info("Registered http default server views")
}
if err := view.Register(ocgrpc.DefaultClientViews...); err != nil {
log.Warn("Error registering grpc default client views")
} else {
log.Info("Registered grpc default client views")
}
}
func initStackdriverTracing(log logrus.FieldLogger) {
// TODO(ahmetb) this method is duplicated in other microservices using Go
// since they are not sharing packages.
for i := 1; i <= 3; i++ {
log = log.WithField("retry", i)
exporter, err := stackdriver.NewExporter(stackdriver.Options{})
if err != nil {
// log.Warnf is used since there are multiple backends (stackdriver & jaeger)
// to store the traces. In production setup most likely you would use only one backend.
// In that case you should use log.Fatalf.
log.Warnf("failed to initialize Stackdriver exporter: %+v", err)
} else {
trace.RegisterExporter(exporter)
log.Info("registered Stackdriver tracing")
// Register the views to collect server stats.
initStats(log, exporter)
return
}
d := time.Second * 20 * time.Duration(i)
log.Debugf("sleeping %v to retry initializing Stackdriver exporter", d)
time.Sleep(d)
}
log.Warn("could not initialize Stackdriver exporter after retrying, giving up")
}
func initTracing(log logrus.FieldLogger) {
// This is a demo app with low QPS. trace.AlwaysSample() is used here
// to make sure traces are available for observation and analysis.
// In a production environment or high QPS setup please use
// trace.ProbabilitySampler set at the desired probability.
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
initJaegerTracing(log)
initStackdriverTracing(log)
}
func initProfiling(log logrus.FieldLogger, service, version string) {
// TODO(ahmetb) this method is duplicated in other microservices using Go
// since they are not sharing packages.
for i := 1; i <= 3; i++ {
log = log.WithField("retry", i)
if err := profiler.Start(profiler.Config{
Service: service,
ServiceVersion: version,
// ProjectID must be set if not running on GCP.
// ProjectID: "my-project",
}); err != nil {
log.Warnf("warn: failed to start profiler: %+v", err)
} else {
log.Info("started Stackdriver profiler")
return
}
d := time.Second * 10 * time.Duration(i)
log.Debugf("sleeping %v to retry initializing Stackdriver profiler", d)
time.Sleep(d)
}
log.Warn("warning: could not initialize Stackdriver profiler after retrying, giving up")
}
func mustMapEnv(target *string, envKey string) {
v := os.Getenv(envKey)
if v == "" {
panic(fmt.Sprintf("environment variable %q not set", envKey))
}
*target = v
}
func mustConnGRPC(ctx context.Context, conn **grpc.ClientConn, addr string) {
var err error
*conn, err = grpc.DialContext(ctx, addr,
grpc.WithInsecure(),
grpc.WithTimeout(time.Second*3),
grpc.WithStatsHandler(&ocgrpc.ClientHandler{}))
if err != nil {
panic(errors.Wrapf(err, "grpc: failed to connect %s", addr))
}
}
// Copyright 2018 Google LLC
//
// 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 (
"context"
"net/http"
"time"
"github.com/google/uuid"
"github.com/sirupsen/logrus"
)
type ctxKeyLog struct{}
type ctxKeyRequestID struct{}
type logHandler struct {
log *logrus.Logger
next http.Handler
}
type responseRecorder struct {
b int
status int
w http.ResponseWriter
}
func (r *responseRecorder) Header() http.Header { return r.w.Header() }
func (r *responseRecorder) Write(p []byte) (int, error) {
if r.status == 0 {
r.status = http.StatusOK
}
n, err := r.w.Write(p)
r.b += n
return n, err
}
func (r *responseRecorder) WriteHeader(statusCode int) {
r.status = statusCode
r.w.WriteHeader(statusCode)
}
func (lh *logHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
requestID, _ := uuid.NewRandom()
ctx = context.WithValue(ctx, ctxKeyRequestID{}, requestID.String())
start := time.Now()
rr := &responseRecorder{w: w}
log := lh.log.WithFields(logrus.Fields{
"http.req.path": r.URL.Path,
"http.req.method": r.Method,
"http.req.id": requestID.String(),
})
if v, ok := r.Context().Value(ctxKeySessionID{}).(string); ok {
log = log.WithField("session", v)
}
log.Debug("request started")
defer func() {
log.WithFields(logrus.Fields{
"http.resp.took_ms": int64(time.Since(start) / time.Millisecond),
"http.resp.status": rr.status,
"http.resp.bytes": rr.b}).Debugf("request complete")
}()
ctx = context.WithValue(ctx, ctxKeyLog{}, log)
r = r.WithContext(ctx)
lh.next.ServeHTTP(rr, r)
}
func ensureSessionID(next http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var sessionID string
c, err := r.Cookie(cookieSessionID)
if err == http.ErrNoCookie {
u, _ := uuid.NewRandom()
sessionID = u.String()
http.SetCookie(w, &http.Cookie{
Name: cookieSessionID,
Value: sessionID,
MaxAge: cookieMaxAge,
})
} else if err != nil {
return
} else {
sessionID = c.Value
}
ctx := context.WithValue(r.Context(), ctxKeySessionID{}, sessionID)
r = r.WithContext(ctx)
next.ServeHTTP(w, r)
}
}
// Copyright 2018 Google LLC
//
// 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 money
import (
"errors"
pb "github.com/GoogleCloudPlatform/microservices-demo/src/frontend/genproto"
)
const (
nanosMin = -999999999
nanosMax = +999999999
nanosMod = 1000000000
)
var (
ErrInvalidValue = errors.New("one of the specified money values is invalid")
ErrMismatchingCurrency = errors.New("mismatching currency codes")
)
// IsValid checks if specified value has a valid units/nanos signs and ranges.
func IsValid(m pb.Money) bool {
return signMatches(m) && validNanos(m.GetNanos())
}
func signMatches(m pb.Money) bool {
return m.GetNanos() == 0 || m.GetUnits() == 0 || (m.GetNanos() < 0) == (m.GetUnits() < 0)
}
func validNanos(nanos int32) bool { return nanosMin <= nanos && nanos <= nanosMax }
// IsZero returns true if the specified money value is equal to zero.
func IsZero(m pb.Money) bool { return m.GetUnits() == 0 && m.GetNanos() == 0 }
// IsPositive returns true if the specified money value is valid and is
// positive.
func IsPositive(m pb.Money) bool {
return IsValid(m) && m.GetUnits() > 0 || (m.GetUnits() == 0 && m.GetNanos() > 0)
}
// IsNegative returns true if the specified money value is valid and is
// negative.
func IsNegative(m pb.Money) bool {
return IsValid(m) && m.GetUnits() < 0 || (m.GetUnits() == 0 && m.GetNanos() < 0)
}
// AreSameCurrency returns true if values l and r have a currency code and
// they are the same values.
func AreSameCurrency(l, r pb.Money) bool {
return l.GetCurrencyCode() == r.GetCurrencyCode() && l.GetCurrencyCode() != ""
}
// AreEquals returns true if values l and r are the equal, including the
// currency. This does not check validity of the provided values.
func AreEquals(l, r pb.Money) bool {
return l.GetCurrencyCode() == r.GetCurrencyCode() &&
l.GetUnits() == r.GetUnits() && l.GetNanos() == r.GetNanos()
}
// Negate returns the same amount with the sign negated.
func Negate(m pb.Money) pb.Money {
return pb.Money{
Units: -m.GetUnits(),
Nanos: -m.GetNanos(),
CurrencyCode: m.GetCurrencyCode()}
}
// Must panics if the given error is not nil. This can be used with other
// functions like: "m := Must(Sum(a,b))".
func Must(v pb.Money, err error) pb.Money {
if err != nil {
panic(err)
}
return v
}
// Sum adds two values. Returns an error if one of the values are invalid or
// currency codes are not matching (unless currency code is unspecified for
// both).
func Sum(l, r pb.Money) (pb.Money, error) {
if !IsValid(l) || !IsValid(r) {
return pb.Money{}, ErrInvalidValue
} else if l.GetCurrencyCode() != r.GetCurrencyCode() {
return pb.Money{}, ErrMismatchingCurrency
}
units := l.GetUnits() + r.GetUnits()
nanos := l.GetNanos() + r.GetNanos()
if (units == 0 && nanos == 0) || (units > 0 && nanos >= 0) || (units < 0 && nanos <= 0) {
// same sign <units, nanos>
units += int64(nanos / nanosMod)
nanos = nanos % nanosMod
} else {
// different sign. nanos guaranteed to not to go over the limit
if units > 0 {
units--
nanos += nanosMod
} else {
units++
nanos -= nanosMod
}
}
return pb.Money{
Units: units,
Nanos: nanos,
CurrencyCode: l.GetCurrencyCode()}, nil
}
// MultiplySlow is a slow multiplication operation done through adding the value
// to itself n-1 times.
func MultiplySlow(m pb.Money, n uint32) pb.Money {
out := m
for n > 1 {
out = Must(Sum(out, m))
n--
}
return out
}
// Copyright 2018 Google LLC
//
// 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 money
import (
"fmt"
"reflect"
"testing"
pb "github.com/GoogleCloudPlatform/microservices-demo/src/frontend/genproto"
)
func mmc(u int64, n int32, c string) pb.Money { return pb.Money{Units: u, Nanos: n, CurrencyCode: c} }
func mm(u int64, n int32) pb.Money { return mmc(u, n, "") }
func TestIsValid(t *testing.T) {
tests := []struct {
name string
in pb.Money
want bool
}{
{"valid -/-", mm(-981273891273, -999999999), true},
{"invalid -/+", mm(-981273891273, +999999999), false},
{"valid +/+", mm(981273891273, 999999999), true},
{"invalid +/-", mm(981273891273, -999999999), false},
{"invalid +/+overflow", mm(3, 1000000000), false},
{"invalid +/-overflow", mm(3, -1000000000), false},
{"invalid -/+overflow", mm(-3, 1000000000), false},
{"invalid -/-overflow", mm(-3, -1000000000), false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := IsValid(tt.in); got != tt.want {
t.Errorf("IsValid(%v) = %v, want %v", tt.in, got, tt.want)
}
})
}
}
func TestIsZero(t *testing.T) {
tests := []struct {
name string
in pb.Money
want bool
}{
{"zero", mm(0, 0), true},
{"not-zero (-/+)", mm(-1, +1), false},
{"not-zero (-/-)", mm(-1, -1), false},
{"not-zero (+/+)", mm(+1, +1), false},
{"not-zero (+/-)", mm(+1, -1), false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := IsZero(tt.in); got != tt.want {
t.Errorf("IsZero(%v) = %v, want %v", tt.in, got, tt.want)
}
})
}
}
func TestIsPositive(t *testing.T) {
tests := []struct {
name string
in pb.Money
want bool
}{
{"zero", mm(0, 0), false},
{"positive (+/+)", mm(+1, +1), true},
{"invalid (-/+)", mm(-1, +1), false},
{"negative (-/-)", mm(-1, -1), false},
{"invalid (+/-)", mm(+1, -1), false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := IsPositive(tt.in); got != tt.want {
t.Errorf("IsPositive(%v) = %v, want %v", tt.in, got, tt.want)
}
})
}
}
func TestIsNegative(t *testing.T) {
tests := []struct {
name string
in pb.Money
want bool
}{
{"zero", mm(0, 0), false},
{"positive (+/+)", mm(+1, +1), false},
{"invalid (-/+)", mm(-1, +1), false},
{"negative (-/-)", mm(-1, -1), true},
{"invalid (+/-)", mm(+1, -1), false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := IsNegative(tt.in); got != tt.want {
t.Errorf("IsNegative(%v) = %v, want %v", tt.in, got, tt.want)
}
})
}
}
func TestAreSameCurrency(t *testing.T) {
type args struct {
l pb.Money
r pb.Money
}
tests := []struct {
name string
args args
want bool
}{
{"both empty currency", args{mmc(1, 0, ""), mmc(2, 0, "")}, false},
{"left empty currency", args{mmc(1, 0, ""), mmc(2, 0, "USD")}, false},
{"right empty currency", args{mmc(1, 0, "USD"), mmc(2, 0, "")}, false},
{"mismatching", args{mmc(1, 0, "USD"), mmc(2, 0, "CAD")}, false},
{"matching", args{mmc(1, 0, "USD"), mmc(2, 0, "USD")}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := AreSameCurrency(tt.args.l, tt.args.r); got != tt.want {
t.Errorf("AreSameCurrency([%v],[%v]) = %v, want %v", tt.args.l, tt.args.r, got, tt.want)
}
})
}
}
func TestAreEquals(t *testing.T) {
type args struct {
l pb.Money
r pb.Money
}
tests := []struct {
name string
args args
want bool
}{
{"equals", args{mmc(1, 2, "USD"), mmc(1, 2, "USD")}, true},
{"mismatching currency", args{mmc(1, 2, "USD"), mmc(1, 2, "CAD")}, false},
{"mismatching units", args{mmc(10, 20, "USD"), mmc(1, 20, "USD")}, false},
{"mismatching nanos", args{mmc(1, 2, "USD"), mmc(1, 20, "USD")}, false},
{"negated", args{mmc(1, 2, "USD"), mmc(-1, -2, "USD")}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := AreEquals(tt.args.l, tt.args.r); got != tt.want {
t.Errorf("AreEquals([%v],[%v]) = %v, want %v", tt.args.l, tt.args.r, got, tt.want)
}
})
}
}
func TestNegate(t *testing.T) {
tests := []struct {
name string
in pb.Money
want pb.Money
}{
{"zero", mm(0, 0), mm(0, 0)},
{"negative", mm(-1, -200), mm(1, 200)},
{"positive", mm(1, 200), mm(-1, -200)},
{"carries currency code", mmc(0, 0, "XXX"), mmc(0, 0, "XXX")},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Negate(tt.in); !AreEquals(got, tt.want) {
t.Errorf("Negate([%v]) = %v, want %v", tt.in, got, tt.want)
}
})
}
}
func TestMust_pass(t *testing.T) {
v := Must(mm(2, 3), nil)
if !AreEquals(v, mm(2, 3)) {
t.Errorf("returned the wrong value: %v", v)
}
}
func TestMust_panic(t *testing.T) {
defer func() {
if r := recover(); r != nil {
t.Logf("panic captured: %v", r)
}
}()
Must(mm(2, 3), fmt.Errorf("some error"))
t.Fatal("this should not have executed due to the panic above")
}
func TestSum(t *testing.T) {
type args struct {
l pb.Money
r pb.Money
}
tests := []struct {
name string
args args
want pb.Money
wantErr error
}{
{"0+0=0", args{mm(0, 0), mm(0, 0)}, mm(0, 0), nil},
{"Error: currency code on left", args{mmc(0, 0, "XXX"), mm(0, 0)}, mm(0, 0), ErrMismatchingCurrency},
{"Error: currency code on right", args{mm(0, 0), mmc(0, 0, "YYY")}, mm(0, 0), ErrMismatchingCurrency},
{"Error: currency code mismatch", args{mmc(0, 0, "AAA"), mmc(0, 0, "BBB")}, mm(0, 0), ErrMismatchingCurrency},
{"Error: invalid +/-", args{mm(+1, -1), mm(0, 0)}, mm(0, 0), ErrInvalidValue},
{"Error: invalid -/+", args{mm(0, 0), mm(-1, +2)}, mm(0, 0), ErrInvalidValue},
{"Error: invalid nanos", args{mm(0, 1000000000), mm(1, 0)}, mm(0, 0), ErrInvalidValue},
{"both positive (no carry)", args{mm(2, 200000000), mm(2, 200000000)}, mm(4, 400000000), nil},
{"both positive (nanos=max)", args{mm(2, 111111111), mm(2, 888888888)}, mm(4, 999999999), nil},
{"both positive (carry)", args{mm(2, 200000000), mm(2, 900000000)}, mm(5, 100000000), nil},
{"both negative (no carry)", args{mm(-2, -200000000), mm(-2, -200000000)}, mm(-4, -400000000), nil},
{"both negative (carry)", args{mm(-2, -200000000), mm(-2, -900000000)}, mm(-5, -100000000), nil},
{"mixed (larger positive, just decimals)", args{mm(11, 0), mm(-2, 0)}, mm(9, 0), nil},
{"mixed (larger negative, just decimals)", args{mm(-11, 0), mm(2, 0)}, mm(-9, 0), nil},
{"mixed (larger positive, no borrow)", args{mm(11, 100000000), mm(-2, -100000000)}, mm(9, 0), nil},
{"mixed (larger positive, with borrow)", args{mm(11, 100000000), mm(-2, -9000000 /*.09*/)}, mm(9, 91000000 /*.091*/), nil},
{"mixed (larger negative, no borrow)", args{mm(-11, -100000000), mm(2, 100000000)}, mm(-9, 0), nil},
{"mixed (larger negative, with borrow)", args{mm(-11, -100000000), mm(2, 9000000 /*.09*/)}, mm(-9, -91000000 /*.091*/), nil},
{"0+negative", args{mm(0, 0), mm(-2, -100000000)}, mm(-2, -100000000), nil},
{"negative+0", args{mm(-2, -100000000), mm(0, 0)}, mm(-2, -100000000), nil},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Sum(tt.args.l, tt.args.r)
if err != tt.wantErr {
t.Errorf("Sum([%v],[%v]): expected err=\"%v\" got=\"%v\"", tt.args.l, tt.args.r, tt.wantErr, err)
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("Sum([%v],[%v]) = %v, want %v", tt.args.l, tt.args.r, got, tt.want)
}
})
}
}
// Copyright 2018 Google LLC
//
// 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 (
"context"
"time"
pb "github.com/GoogleCloudPlatform/microservices-demo/src/frontend/genproto"
"github.com/pkg/errors"
)
const (
avoidNoopCurrencyConversionRPC = false
)
func (fe *frontendServer) getCurrencies(ctx context.Context) ([]string, error) {
currs, err := pb.NewCurrencyServiceClient(fe.currencySvcConn).
GetSupportedCurrencies(ctx, &pb.Empty{})
if err != nil {
return nil, err
}
var out []string
for _, c := range currs.CurrencyCodes {
if _, ok := whitelistedCurrencies[c]; ok {
out = append(out, c)
}
}
return out, nil
}
func (fe *frontendServer) getProducts(ctx context.Context) ([]*pb.Product, error) {
resp, err := pb.NewProductCatalogServiceClient(fe.productCatalogSvcConn).
ListProducts(ctx, &pb.Empty{})
return resp.GetProducts(), err
}
func (fe *frontendServer) getProduct(ctx context.Context, id string) (*pb.Product, error) {
resp, err := pb.NewProductCatalogServiceClient(fe.productCatalogSvcConn).
GetProduct(ctx, &pb.GetProductRequest{Id: id})
return resp, err
}
func (fe *frontendServer) getCart(ctx context.Context, userID string) ([]*pb.CartItem, error) {
resp, err := pb.NewCartServiceClient(fe.cartSvcConn).GetCart(ctx, &pb.GetCartRequest{UserId: userID})
return resp.GetItems(), err
}
func (fe *frontendServer) emptyCart(ctx context.Context, userID string) error {
_, err := pb.NewCartServiceClient(fe.cartSvcConn).EmptyCart(ctx, &pb.EmptyCartRequest{UserId: userID})
return err
}
func (fe *frontendServer) insertCart(ctx context.Context, userID, productID string, quantity int32) error {
_, err := pb.NewCartServiceClient(fe.cartSvcConn).AddItem(ctx, &pb.AddItemRequest{
UserId: userID,
Item: &pb.CartItem{
ProductId: productID,
Quantity: quantity},
})
return err
}
func (fe *frontendServer) convertCurrency(ctx context.Context, money *pb.Money, currency string) (*pb.Money, error) {
if avoidNoopCurrencyConversionRPC && money.GetCurrencyCode() == currency {
return money, nil
}
return pb.NewCurrencyServiceClient(fe.currencySvcConn).
Convert(ctx, &pb.CurrencyConversionRequest{
From: money,
ToCode: currency})
}
func (fe *frontendServer) getShippingQuote(ctx context.Context, items []*pb.CartItem, currency string) (*pb.Money, error) {
quote, err := pb.NewShippingServiceClient(fe.shippingSvcConn).GetQuote(ctx,
&pb.GetQuoteRequest{
Address: nil,
Items: items})
if err != nil {
return nil, err
}
localized, err := fe.convertCurrency(ctx, quote.GetCostUsd(), currency)
return localized, errors.Wrap(err, "failed to convert currency for shipping cost")
}
func (fe *frontendServer) getRecommendations(ctx context.Context, userID string, productIDs []string) ([]*pb.Product, error) {
resp, err := pb.NewRecommendationServiceClient(fe.recommendationSvcConn).ListRecommendations(ctx,
&pb.ListRecommendationsRequest{UserId: userID, ProductIds: productIDs})
if err != nil {
return nil, err
}
out := make([]*pb.Product, len(resp.GetProductIds()))
for i, v := range resp.GetProductIds() {
p, err := fe.getProduct(ctx, v)
if err != nil {
return nil, errors.Wrapf(err, "failed to get recommended product info (#%s)", v)
}
out[i] = p
}
if len(out) > 4 {
out = out[:4] // take only first four to fit the UI
}
return out, err
}
func (fe *frontendServer) getAd(ctx context.Context, ctxKeys []string) ([]*pb.Ad, error) {
ctx, cancel := context.WithTimeout(ctx, time.Millisecond*100)
defer cancel()
resp, err := pb.NewAdServiceClient(fe.adSvcConn).GetAds(ctx, &pb.AdRequest{
ContextKeys: ctxKeys,
})
return resp.GetAds(), errors.Wrap(err, "failed to get ads")
}
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 196.91 188.42">
<defs>
<style>
.cls-1 {
fill: #fff;
}
</style>
</defs>
<title>Hipster</title>
<g>
<g>
<g>
<path class="cls-1" d="M13.05,94.66c-2.61,0-4.25,1.42-4.25,5.15v5.59H1.05v-5.07C1.05,92,5.22,87.2,13.28,87.2S25.51,92,25.51,100.33c0,16.4-16.34,22.52-16.34,31.09a5.24,5.24,0,0,0,.08,1.12H24.76V140H1.05v-6.41c0-15.36,16.25-17.9,16.25-33C17.3,95.93,15.66,94.66,13.05,94.66Z"/>
<path class="cls-1" d="M29.9,100.33C29.9,92,34.3,87.2,42.36,87.2S54.81,92,54.81,100.33v27.14c0,8.35-4.4,13.13-12.45,13.13S29.9,135.82,29.9,127.47ZM38.11,128c0,3.73,1.64,5.15,4.25,5.15s4.25-1.42,4.25-5.15V99.81c0-3.73-1.64-5.15-4.25-5.15s-4.25,1.42-4.25,5.15Z"/>
<path class="cls-1" d="M59.65,95.78c0-5.37,2.76-8.35,7.91-8.35s7.9,3,7.9,8.35v17.15c0,5.37-2.76,8.35-7.9,8.35s-7.91-3-7.91-8.35Zm5.22,17.52c0,2.31,1,3.28,2.69,3.28s2.68-1,2.68-3.28V95.41c0-2.31-1-3.28-2.68-3.28s-2.69,1-2.69,3.28ZM88.14,87.8H93L72.41,140H67.56Zm-2.61,27.07c0-5.37,2.76-8.35,7.9-8.35s7.91,3,7.91,8.35V132c0,5.37-2.76,8.35-7.91,8.35s-7.9-3-7.9-8.35Zm5.22,17.52c0,2.31,1,3.28,2.68,3.28s2.69-1,2.69-3.28V114.5c0-2.31-1.05-3.28-2.69-3.28s-2.68,1-2.68,3.28Z"/>
<path class="cls-1" d="M117.74,100.33c0-8.35,4.4-13.13,12.45-13.13s12.46,4.78,12.46,13.13v27.14c0,8.35-4.4,13.13-12.46,13.13s-12.45-4.78-12.45-13.13Zm8.2,27.66c0,3.73,1.64,5.15,4.25,5.15s4.25-1.42,4.25-5.15V99.81c0-3.73-1.64-5.15-4.25-5.15s-4.25,1.42-4.25,5.15Z"/>
<path class="cls-1" d="M156.14,111h10.59v7.46H156.14V140h-8.2V87.8h21.7v7.46h-13.5Z"/>
<path class="cls-1" d="M181.79,111h10.59v7.46H181.79V140h-8.2V87.8h21.7v7.46h-13.5Z"/>
</g>
<rect class="cls-1" x="1.05" y="150" width="117.58" height="6.14"/>
<rect class="cls-1" x="1.05" y="32.28" width="117.58" height="6.14"/>
</g>
<rect class="cls-1" x="1.05" y="16.14" width="77.58" height="6.14"/>
<rect class="cls-1" x="1.05" width="37.58" height="6.14"/>
<rect class="cls-1" x="1.05" y="166.14" width="77.58" height="6.14"/>
<rect class="cls-1" x="1.05" y="182.28" width="37.58" height="6.14"/>
</g>
<g>
<path class="cls-1" d="M1.5,62.16l-.41-.54L.72,61l-.24-.45L.32,60.2.2,59.66.08,59,0,58.34v-1l0-.37.05-.33,0-.37.26-.74.08-.34.17-.37.17-.29L1,54.24l.17-.37.21-.29.21-.32L2,52.68l.25-.29.54-.53.59-.49.33-.21.83-.57.38-.2.33-.21.62-.32.38-.17.5-.16.41-.16.42-.12.45-.16L8.49,49l.37,0,.33-.08.38,0,.37-.12.37-.08.34,0,.37,0,.41,0,.5,0h.87l1.74.14.91.17.25,0,.82.13.38.09.37.13.33.13.37.12.33.13.33.17.33.13.37.16.45.26.46.29.33.21.33.3.53.37.29.25L22,52l.21.25.49.59.41.66.16.21.21.38.12.33.12.37.24.67.12.37,0,.34.12,1.11v.92l-.05.53v.42l-.09.74-.09.37-.13.38-.08.33-.26.74-.08.33-.17.37-.17.29L22.9,63l-.17.37-.21.33-.21.29-.21.33-.29.33-.17.16-.29.33-.25.29-.29.24-.25.25-.29.25-.67.4L19,67l-.3.16-.33.17-.41.16-.34.08-.74.24-.38.08-.33.08-.37,0L15,68l-.37,0H12.75l-.41,0-.5-.09-.53-.13-.42-.08-.74-.22-.46-.08-.37.08-.17.28L9,68.11l-.13.41-.09.25-.08.45-.09.37-.09.75-.09.37-.25.74-.09.37,0,.38L8,72.57l-.08.37-.13.37,0,.42-.17.74-.13.37-.08.33-.17.37L7,75.92l-.17.32-.21.37L6.3,77l-.54.29-.67.08-.7-.13-.54-.3-.28-.37,0-.38.13-.33.17-.37L4,75l.17-.5.12-.41.13-.5.17-.53.26-.75L5,71.92l.12-.54.09-.45.13-.37.08-.37,0-.38.09-.37.08-.33.09-.37.12-.37.13-.5.13-.53.17-.75.09-.33.09-.45.08-.21.09-.46.08-.33.09-.37.13-.37L7,63.7l.13-.37.09-.54.13-.5.25-.74.26-.66L8,60.52l.09-.37.3-.87.17-.58.13-.25.21-.58.29-.61.21-.5.21-.37.38-.62.21-.33.17-.33.21-.29.25-.28.54-.54.3-.24.66-.33.38-.12.74-.16.42.05.37.08.37.21.24.3.08.37-.12.29-.34.2-.29.21-.33.2-.25.25-.5.57-.21.29-.68,1.32-.16.29-.17.33-.13.37-.09.37-.12.37-.13.5-.17.54-.17.37-.13.54-.13.49-.09.37-.12.42-.05.24-.13.42-.08.37-.13.37,0,.37-.05.46.08.37.29.21.49.17.58.09.25,0,.58.09.54.09h.41l.75,0,.5,0,.53-.08.38-.12.33-.12.37-.16.5-.21.42-.24.67-.41.29-.2.25-.25.75-.86.3-.45.33-.58.25-.46.21-.41.17-.49.13-.5,0-.41.09-.5.12-.54.05-.41,0-.37,0-.38,0-.41-.08-.37-.16-.54-.12-.5-.16-.38L20.07,55l-.2-.33-.2-.29L19.46,54l-.53-.54-.25-.29-.57-.51-.33-.21-.33-.16-.37-.17-1-.43-.38-.16-.37-.13-.7-.17-.41,0-.38,0-1.15-.06h-.38l-.37,0-.75,0-.37,0-.33.08-.37.08-.38.12-.7.16-.75.24L8,52l-.88.45-.41.2-.38.2-1.17,1-.54.53-.25.29L4.13,55l-.21.33-.17.33L3.62,56l-.12.37-.13.33L3.24,57l-.09.74,0,.38v.41l.08.54.07.5.12.37.17.38L4,61l.21.33.16.34,0,.33-.17.37-.25.29-.3.24-.37.16-.37.08-.38-.08-.37-.3-.28-.29Z"/>
<path class="cls-1" d="M35.83,75.55l-.58.49-.67.41-.33.16-.67.41-.33.16-.75.24-.41.12-.75.12-.25.08-.41.08-.33,0H30l-.45,0h-.38l-.74-.09L28,77.67l-.38-.12-.29-.13-.37-.13-.33-.17-.66-.42-.28-.25-.49-.58-.21-.34-.16-.33-.21-.33-.24-.75-.16-.75-.07-.74,0-.42,0-.37V70.68l.09-.37.09-.33.08-.37.13-.75.09-.41.09-.37.12-.33.13-.37L25.1,67l.17-.34.12-.37.22-.49.25-.5.21-.33.25-.33.21-.28.25-.29.42-.66.25-.29L28,62.6l.58-.49.29-.21.33-.24.38-.25.46-.28.46-.25.33-.16.41-.16.25-.08.46-.17.25-.08.41-.12L33,60l.41,0,.37,0h1l.66.09.54.08.37.09.37.13.33.16.74.47.45.25.29.25.21.25.24.29.25.34.49.91.12.37,0,.38,0,.33.15.75v1.45l-.09.49,0,.46-.05.41-.26,1.24-.17.58-.12.41-.17.41-.17.46-.13.37-.25.45-.38.75L38,73l0,.29.33,0h.24l.46,0,.29,0,.37-.08.42-.16.29-.16.67-.41.29-.25.54-.53.51-.58.2-.29.21-.33.21-.28.34-.66.38-.7.13-.25.25-.37.37-.21.5.09.33.38,0,.45-.12.37-.51,1-.21.29-.42.66-.17.33-.21.29-.25.33-.21.29-.25.24-.54.58-.25.24-.29.25-.3.2-.33.25-.29.16-.67.33-.37.16-.33.08-1.49.15-.46,0-.37,0L37,75l-.33,0-.29.13-.3.2ZM27.67,71l0,.5,0,.41,0,.54.08.66.16.67.28.62.29.42.33.29.45.21.62.17h.54l.41,0,.42-.08.37-.16L32,75l.37-.21.33-.2.3-.25.33-.24.17-.29v-.25l-.16-.29L33.12,73,33,72.58l.09-.49.17-.5.29-.25.33-.2.38,0,.37.09.29.08.25,0,.17-.24.12-.33L36,69.17l.26-1.11.09-.54.13-.7.09-1.41,0-.67-.16-.7-.24-.62L35.86,63l-.33-.25L35,62.54l-.62-.13-.54,0h-.42l-.33.08-.37.12-.42.24L32,63l-.38.24-.41.33-.3.25-.29.28-.21.29-.25.29L30,65l-.42.57-.21.33-.84,1.65-.13.37-.08.33L28,69l-.08.33-.13.37,0,.37v.37Z"/>
<path class="cls-1" d="M68.11,68.79l0,.58-.21.49-.21.37-.17.34-.21.37-.08.24-.51.83-.25.45-.25.33-.17.33-.21.33-.21.29-.25.33-.29.37-.34.45-.25.33-.5.57L63.7,76l-.3.25-.25.24-.29.25-.33.2-.29.21-1.33.65-.38.12-.37.08-.37,0h-.92l-.49,0L58,77.94l-.54-.17-.62-.3-.53-.38L56,76.72l-.41-.67-.17-.33-.2-.5L55,74.6l0-.54v-.42l-.08-.37h-.21l-.25.29-.29.28-.5.58-.46.62-.51.57-.29.25-.62.49-.34.24-.91.58-.38.2-.33.2-.33.17-.75.16L47.57,78H47.2L46.82,78l-.37-.08-.33-.13-.37-.13-.33-.17-.29-.21-.57-.5-.41-.58L44,75.78l-.12-.33-.13-.37-.07-.38,0-.37,0-.33v-.75l0-.41v-.75l0-.33,0-.37.05-.41.13-1.12.05-.33.08-.37.13-.37.09-.37.08-.34.09-.37,0-.41.13-.54.13-.49.09-.42.17-.74.13-.5.13-.54.12-.37.09-.37.09-.33.17-.74.25-.75.09-.33.13-.37.08-.37v-.29l-.12-.21-.33-.08-.54-.09-.57-.13-.38-.13L44,59.26l-.24-.38v-.37l.05-.37.17-.33.21-.29.33-.2h.37l.37.09.42,0,.37.09.41,0h.33l.21-.17.13-.29.25-.74.13-.33.13-.37.21-.7.09-.38L48,54.2l.13-.5.13-.53.09-.37.13-.38.16-.37.17-.49.22-.5.29-.2.41-.12.38,0h.41l.37.09.37.13.33.16.29.26.16.33L52,52l-.09.41-.17.75-.13.37-.08.37-.09.33-.13.37-.12.42-.26.74-.08.37-.13.37-.09.37-.13.38v.29l.29.16.54,0,1.45,0,.7,0,.5,0,.29.25.08.34,0,.37-.08.37-.13.37-.21.29-.33.2-.38.08-1.11.12-.42,0h-.83l-.25,0h-.45l-.33,0-.21.16-.13.33-.13.38-.08.37-.13.37-.21.7-.09.37-.08.33-.09.37L48.6,64l-.08.37-.13.37-.13.34-.08.37-.13.41,0,.37,0,.33-.09.37-.25.75-.52,2.23,0,.37-.26,1.12,0,.41-.18,1.49,0,.37,0,.42.08.33.12.37.21.34.28.25.33.17.42.08.49,0,.59-.16.49-.21.5-.28.21-.08.38-.25.29-.2.54-.54.25-.2.29-.25.25-.29.3-.32.12-.21.25-.33.51-.57.21-.29.29-.42.67-1,.29-.46.26-.45.29-.41.17-.37.13-.37.08-.37.13-.38.09-.33.08-.37.13-.37.09-.37.12-.33.09-.37.09-.42L57,63.52l.13-.33.09-.38.13-.74.08-.46.05-.24.13-.46.12-.37v-.29L57.5,60l-.58-.17-.62-.17-.53-.26L55.48,59l0-.37.05-.38.17-.37.25-.24.33-.17.5,0,.57,0,.25.05h.54l.38-.28.21-.42.13-.41.12-.33.13-.37.09-.33.12-.37.17-.75.13-.37.09-.37.13-.33.38-1.12.13-.49.21-.5.29-.24.42-.08.37,0H62l.37.09.38.13.33.21.32.25.17.29v.37l-.25.75-.09.41-.12.37-.18.75-.63,1.85-.09.38-.13.41-.13.37,0,.33.12.17.33.08.38,0h.37l.45,0h.29l.42,0,1-.12.62,0,.42,0,.29,0,.24.21.09.37,0,.33-.09.38-.12.37-.21.33-.29.2-.54.12-.58.08-.83,0-.63,0h-.7l-1.32.07-.38.21-.17.33-.13.33-.12.37-.09.37-.08.33-.13.37-.09.38-.13.41-.08.37-.09.33-.13.37-.12.5-.17.54-.13.37L59.22,67l0,.38-.18.74-.08.29-.13.37-.09.41,0,.38-.17.74-.05.37V71l0,.38,0,.41-.09.37-.09.75,0,.37v.37l0,.38.08.37.16.33.2.33.25.3.29.21.37.12h.33l.41-.08.38-.12.33-.12.67-.41.29-.25.29-.2.54-.54.3-.33.5-.49.5-.57.25-.33L64.6,72l.46-.66.13-.21.25-.37.63-1,.21-.37.13-.25.21-.37.25-.33.37-.21.54.09Z"/>
<path class="cls-1" d="M79.83,67.94l-.21.29-.5.57-.58.49-.3.21-.37.2-.25.08L77.2,70l-.25.12-.37.16-.41.12-.38.13-.37,0-.42.08-.45,0-.5.08-.37,0H73.3l-.74-.09-.74,0-.38,0-1.11-.26H70l-.21.16-.09.29v.38l0,.41v.7l0,.42.08.33.24.75.41.66.24.3L71,75l.66.42.41.12.37.13.29,0,.37.08.38,0h.41l.37,0,1.08-.19.37-.08.38-.13.33-.12.71-.28.66-.33.59-.45.29-.2.29-.25.59-.53.5-.58.21-.28.25-.33.42-.58.21-.33.17-.33.21-.33.16-.33.21-.29.17-.33.17-.37.17-.33.21-.33.29-.2h.37l.37.26.21.37,0,.37-.17.37-.21.46-.25.45-.21.45-.25.46-.25.41L82,72.6l-.13.24-.25.38-.42.57-.25.29-.25.25-.25.28-.3.33-.12.17-.3.33-.25.28-.58.49-.42.33-.37.33-.67.41-1,.45-.33.12-.37.12-.54.08-.5.12-.87.07-.54,0-.46,0h-.37l-1.49-.18-.33-.08-.37-.13-.37-.17-.33-.17-.66-.38L68.53,77l-.29-.25L68,76.49l-.16-.21L67.5,76l-.24-.29-.21-.34L66.89,75l-.16-.37-.12-.33L66.49,74l-.08-.37-.08-.33-.08-.38-.12-1.12V71l0-.38v-.37l.25-1.11.13-.33.09-.38.13-.37.08-.37.13-.37.17-.45.21-.5.21-.37.25-.45.3-.42.17-.37.21-.28.25-.29.62-.66.63-.62.33-.28.38-.29.42-.29.37-.28.42-.25.41-.2.38-.16.54-.25.87-.28.75-.16.54-.08h.91l.53.09.67.13.53.13.37.13.38.17.33.16.24.17.58.5.24.3.25.41.2.5.12.38.08.37,0,.37v.5l-.05.54,0,.41-.12.5-.17.49-.17.41-.13.21-.21.37Zm-5-5-.58.24-.5.24-.33.21-.59.49-.37.37-.34.37-.29.33-.29.45-.3.41-.21.37-.25.46-.17.49-.17.37-.12.33,0,.29.21.21.53.13.83,0,.42.05h1.16l.41-.08.37-.08.42-.16.25-.09.41-.2.3-.2.29-.25.29-.29.29-.24.25-.33.21-.29.17-.33.21-.37.26-.74.08-.42,0-.37,0-.41-.16-.38-.25-.29L76.89,63l-.37-.17-.37-.09-.37,0-.42.08Z"/>
<path class="cls-1" d="M84.87,64.59l.29-.29.5-.57.88-.74.29-.21.33-.24.3-.21.33-.16.37-.16.63-.33.37-.2.75-.24.33-.12L91,61l.37,0,.42,0,.74-.08h1l.54.09.46.09.29,0,.25-.12.16-.29.09-.37.26-.74.08-.33.13-.38.29-.7.13-.41.09-.25.17-.41.08-.33.26-.75.12-.33.43-1.23.21-.5.26-.74.12-.33.17-.42.09-.24.33-.75.13-.33.38-.7.17-.33.37-.28.46-.16h.42l.37,0,.41.09.25.09.41.12.29.21.12.33-.08.33-.09.38-.17.37-.17.33-.12.33-.13.37-.21.5-.17.49L101,54l-.51,1.33-.17.49-.21.5-.13.37-.13.33-.3.87-.21.49-.12.41L98.7,60.2l-.09.37-.13.33-.12.37-.13.33L98.1,62,98,62.3l-.09.37L97.8,63l-.08.38-.13.37-.13.33-.13.37-.08.37-.09.33-.08.37L97,65.9l-.13.53-.17.54-.08.25-.13.45-.09.37-.09.5-.08.54-.26,1.11,0,.38-.08.37-.09.54-.09.49,0,.37-.09.38,0,.37v.37l0,.42,0,.53.12.5.12.38.25.25.33.12.37,0,.33-.08.37-.12.34-.21.75-.65.29-.29.42-.58.42-.66.59-.82.21-.33.17-.33.21-.37.42-.91.21-.37.17-.28.17-.38.21-.45.45-.33.5.09.29.42v.53l-.21.5-.21.41-.25.46-.26.53-.16.25-.51,1-.25.37-.55.86-.42.66-.21.29-.25.33-.21.29-.25.24-.29.25-.29.33-.17.16-.29.33-.29.25-.34.2-.29.16-.33.17L96.1,78l-.37.08h-.34l-.37,0-.37,0L94.28,78,94,77.8l-.33-.21-.25-.21-.29-.29-.41-.59-.16-.33-.12-.38-.08-.33-.11-1.12v-.78l-.08,0-.21.28-.21.33-.38.66-.21.29-.25.29-.46.57-.25.25-.88.74-.37.28-.42.33-.37.25-.34.16-.41.12-1,.2-.41.08-.37,0-.33,0-.38,0-.37-.09-.33-.08L83.84,78l-.29-.17-.33-.25-.37-.38-.37-.33-.2-.34-.16-.33L82,75.79l-.25-.67-.12-.37,0-.38,0-.49v-.54l0-.37v-.38l0-.41.05-.5.09-.53.08-.38.13-.41,0-.25.13-.41.13-.37.38-1,.13-.37.33-.66.26-.46.21-.45.25-.41.17-.21.25-.33.42-.57Zm8.46-1.38-.79,0h-.37l-.37.08-.42.08-.25.08-.41.17-.38.12-.37.16-.34.2-.29.21-.29.24-.29.29-.59.49-.25.25-.25.29-.5.61L87,66.8l-.21.37-.5.91-.21.33-.13.33-.13.37-.13.33-.17.37-.25,1-.13.37-.09.54,0,.5,0,.41.08.54.08.66.08.54.12.38.2.29.25.25.28.25.38.17.49.09.5,0,.41-.16.25-.12.38-.21.29-.2.5-.49.29-.33.26-.29.29-.29.21-.29.21-.33.25-.37.29-.49.3-.37.17-.33.16-.37.13-.33.17-.37.21-.5.21-.45.17-.37.13-.33L93.25,67l.17-.53.35-1.33.13-.53.12-.42.09-.45L94,63.39l-.29-.17Z"/>
<path class="cls-1" d="M120.07,78.56l-.91-.17-.37-.13-.5-.21-.45-.21-.33-.21-.29-.25-.29-.21-.86-.75-.49-.5-.25-.3-.16-.33-.41-.62-.33-.67-.12-.37-.12-.34-.16-.37-.16-.46-.12-.49-.08-.42-.08-.37,0-.38-.08-.54-.08-.49,0-.38V68.23l0-.37v-.37l0-.37,0-.54,0-.5.08-.41,0-.33,0-.37,0-.42.08-.37.09-.54.13-.49.17-.75.13-.37.17-.54.3-.86.12-.33.13-.38.17-.32.17-.38.25-.45.21-.5.21-.37.51-.9.13-.33v-.33l-.12-.29-.21-.34-.2-.37-.2-.46-.25-.46-.16-.41-.16-.5-.16-.46-.12-.41-.12-.5-.17-.54-.15-.75,0-.37.17-.46.46-.28h.62l.49.3.25.46,0,.37.08.37.12.42.12.37.13.33.12.38.16.37.37.71.16.37.16.25h.21l.5-.49.25-.28.75-.74.38-.33.29-.25.33-.2.38-.25.21-.16.33-.25.37-.2,1.38-.73.66-.33.34-.12.74-.16.38-.12.37-.08,1.16-.16.75-.07h.37l.41,0H129l.45.09h.25l.45.09.33.08.38.17.33.13.37.17.33.16.33.21.28.21.29.26.33.33.21.29.2.33.16.34.16.37.13.33.08.38.08.41.07.75v.78l-.08.34-.09.41-.13.37-.12.33-.17.37-.17.33-.21.33-.21.29-.25.33-.42.57-.29.29-.25.29-.59.49-.29.21-.33.2-.29.21L130,61l-.45.2-.54.16-.42.16-.37.12-.38.08-.33,0-.95.08-.54,0h-.83l-.74-.09-.29-.09-.38,0-.94-.3L122,61l-.49-.17-.33-.17-.33-.21-.33-.16-.33-.21-.33-.17-.33-.21-.29-.21-.29-.17-.2.08-.17.25-.47,1.15-.25.66-.17.5-.13.41-.09.33-.12.37-.09.54-.09.5-.09.74,0,.42,0,.53,0,.67,0,.53v.92l0,.53v.42l0,.54.12.66,0,.54.08.41.12.5.29.87.24.5.24.63.29.45.2.34.21.29.24.29.41.34.42.29.37.17.33.13L121,76l.54.13.66.09h.91l.37,0,.91-.16.5-.08.42-.12.5-.16.62-.28.83-.41.33-.2.3-.21.83-.65.88-.74.33-.41.34-.37.54-.78.29-.42.26-.32.21-.29.21-.33.25-.46.29-.41.33-.16.5.17.33.38,0,.45-.17.37-.17.33-.21.37-.51.91-.21.37-.84,1.15-.29.33-.25.33-.38.37-.33.41-.59.54-.29.24-.25.25-.37.24-.17.17-.38.24-.58.41-.33.21-.38.16-.33.16-.7.24-.38.12-.33.12-.37.09-.38.12-.33.08-.37,0-1.16.16h-.71l-.37,0h-.41Zm6.44-26.32-.42.08-.41.12-.54.2-.5.16-.33.17-.33.2-.34.16-.66.41-.3.21-.29.28-.25.29-.21.21-.25.28-.33.33-.25.29-.3.29-.21.33-.21.45.08.5.33.37.66.42.29.21.33.17.28.21.38.13.33.09.74.21.37.08,1.08.1H126l.38,0,.37-.08.33-.08.38-.13.49-.2.46-.24.34-.21.58-.49.25-.25.25-.32.21-.29.68-1.32.08-.37,0-.37v-.34l0-.37-.16-.37-.29-.42-.32-.42-.29-.25-.33-.17-.37-.12-.33-.09-.38-.09-.37,0h-.37Z"/>
<path class="cls-1" d="M152.52,70.69l-.09.21-.21.41-.21.29-.17.33-.17.37-.16.33-.42.66-.21.28-.21.33-.17.33-.21.33-.25.29-.25.33-.25.29-.47.57-.25.29-.25.25-1.17,1-.33.21-.37.2-.46.2-.5.21-.37.12-.38.08h-.41l-.5,0-.49-.13-.37-.13-.29-.21-.29-.25-.29-.42-.28-.45-.12-.38-.12-.5,0-.54v-.41l.05-.54,0-.49-.13-.09-.21.29-.42.66-.42.58-.25.28-.21.29-.25.29-.21.29-.29.24-.25.25-.29.24-.29.21-.34.2-.45.29-.63.28-.66.21-.54.11-.75.08-.41,0-.5-.09-.49-.13-.38-.13-.33-.12-.28-.21-.58-.51-.2-.29-.21-.33-.24-.46-.25-.62-.12-.54,0-.42-.08-.53,0-.67v-.54l0-.41,0-.54.09-.49.12-.42.13-.49.13-.54.13-.37.17-.33.13-.37,1-2,.21-.33.21-.29.21-.33.42-.57.25-.29.54-.62.17-.16.29-.33.58-.49.38-.37.46-.33.58-.45.34-.21.29-.2.37-.16.5-.21.46-.24.41-.2.5-.16.5-.12.41-.13,1-.07.37,0h.5l.83,0,.95.09.91.17.37.09.46.13,1.65.76.28.25.29.21.29.25.25.29.07.46-.17.57-.46.5-.45.28-.34,0-.33-.13-.32-.25-.38-.21-.33-.21-.28-.12-.33-.17-.37-.17-.34-.09-.7-.17-.41-.13-.41-.08h-.83l-.29,0-.42,0-.54.12-1,.36-.41.2-.42.25-.29.2-.33.21-.29.2-.3.25-.33.28-.17.17-.29.33-.25.28-.21.29-.5.58-.21.29-.21.32-.51,1-.21.33-.25.75-.17.37-.17.33L135,71.61l-.13.42-.13,1.11V74.3l0,.42.12.37.16.33.2.34.25.25.37.17.5.08.54,0,.37-.12.67-.33.58-.49.25-.25.29-.24.25-.29.21-.29.25-.29.21-.28.47-.62.2-.29.63-1,.26-.45.29-.54.17-.24.51-1.08.17-.37.08-.29.17-.37.13-.33.12-.37.17-.45.26-.83.17-.45.13-.42.25-.37.41-.2.38-.08.37,0,.37.09.66.34.33.21.17.25,0,.37-.12.33-.09.37-.13.37-.17.75-.13.37-.08.33-.26.74-.08.42,0,.24-.13.5-.08.37-.17.7-.13.5-.09.41-.09.46-.13.62-.13.7,0,.62,0,.54.21.33.41.21.62,0,.5-.16.37-.2.59-.41.29-.29.5-.53.5-.58.42-.57.21-.33.25-.33.09-.25.67-1,.17-.33.21-.33.84-1.65L152,69l.49.09.33.41,0,.42-.17.37Z"/>
<path class="cls-1" d="M156.33,78.84l-.33,0-.37-.09-.37-.13-.49-.21-.46-.25-.37-.21-.41-.34-.37-.37-.29-.25-.24-.3-.25-.25-.16-.33L152,75.7l-.2-.5-.2-.46-.12-.37-.12-.54-.08-.5,0-.41,0-.38V71.8l0-.33.05-.38,0-.41.09-.5.13-.53.13-.37.08-.38.3-.86.21-.46.21-.37.68-1.32.21-.33.42-.57.58-.62.13-.16.29-.33.29-.25.25-.24.29-.25.3-.2.33-.25.29-.21.33-.16.34-.2.29-.16.33-.17.46-.2.87-.24.46-.12.37-.08.37,0,.42,0h.7l.37,0,.54.09.62.17.54.17.37.13.29.17.29.21.28.25.25.29.25.25.16.38.16.45.12.5,0,.42-.05.49-.13.54-.12.37-.17.33-.21.33-.3.41-.29.37-.25.29L164,68l-.34.16-.53.08h-.67l-.66-.17-.41-.29v-.42l.21-.37.3-.45.25-.37.17-.37.08-.33.09-.38v-.33l-.08-.37-.28-.42-.41-.29-.38-.13-.37,0-.37,0-.5.08-.5.16-.37.17-.29.2-.34.25-.29.2-.33.25-.34.37-.29.28-.29.37-.38.46-.25.45-.17.37-.21.33-.17.29-.17.33-.12.37-.13.33-.13.37-.13.54-.13.49-.08.42-.09.49-.05.54,0,.42v.53l0,.67.12.58.12.41.41.83.24.34.25.25.29.25.45.21.5.21.37.09.54.09H159l1-.07.37-.08.46-.12.37-.16.46-.25.46-.2,1-.61.41-.33.38-.33.58-.49.51-.58.25-.24.5-.58.42-.57.25-.37.13-.25.29-.45.25-.42.17-.37.3-.53.41-.29.54.09.33.37v.46l-.12.33-.17.33-.17.37-.21.41-.29.46-.34.45-.34.49-.63.91-.25.33-.21.29-.29.28-.75.87-.21.28-.25.25-.29.25-.59.4-.25.21-.29.2-.37.29-.34.2-.33.17-.33.2-.5.21-.5.16-.46.12-.49.07-.5.12-.75.12-1.12.12-.74-.09Z"/>
<path class="cls-1" d="M180.6,69.74v.45l-.17.41-.5.91-.17.37-.17.33-.42.66-.17.29-.21.33-.33.62-.17.29-.25.37-.5.57-.21.33-.21.29-.26.29-.79.78-.58.45-.59.49-.33.24-.46.25-.5.2-.37.16-.37.12-.34.08-.37,0H171l-.37,0-.37-.09-.5-.17-.45-.21-.33-.21-.58-.5-.2-.29L168,77.2l-.32-.66-.12-.33-.12-.38-.08-.37-.08-.33v-.38l0-.37V74l0-.42v-.37l.13-1.12v-.37l.22-1.86.09-.37,0-.37.17-.75.13-.53.13-.5.09-.37.13-.37.08-.38.13-.37.08-.37.09-.5.17-.53.26-.75v-.33l-.12-.21-.29-.08L168.4,63,168,63l-.41-.17-.28-.38-.08-.37,0-.41.08-.34.17-.28.29-.21.54,0,.62,0h.62l.42-.12.17-.29.08-.42.09-.33.13-.37.17-.33.16-.37.13-.33.26-.74.17-.75.13-.37.17-.33.25-.74L172,55l.17-.37.12-.37.13-.33.13-.37.17-.33.17-.38.08-.33.13-.37.17-.37.21-.29.33-.2.37-.08.42,0,.49.09.54.13.37.21.33.29.12.46-.09.37-.21.54-.25.58-.21.53-.13.42-.09.24-.12.42-.47,1.36-.13.33-.13.37-.17.54-.25.62-.3.86-.08.38-.17.33-.13.33v.29l.25.2.45.09h.41l.71,0,.58,0h1.28l.54,0,.29.25.08.46v.54l-.13.37-.21.29-.29.2-.37.12-.37.08-.42,0-1.12,0h-.45l-.37-.05h-1.54l-.25.16-.12.33-.17.5-.18.66-.17.7-.21.66-.17.7-.17.67-.13.57-.05.25-.13.58-.12.46-.13.41-.17.74-.05.5-.09.54-.09.74v1.16l.08.54.08.5.12.37.16.37.21.3.45.29.58.25.45.09h.42l.45-.07,1-.49,1.17-1,.29-.28.21-.25.42-.53.54-.66.21-.29.17-.33.21-.33.25-.33.21-.29.21-.33.17-.33.13-.37.21-.41L179,70l.25-.41.5-.33.54.09Z"/>
<path class="cls-1" d="M188.75,69.89v.46l-.13.37-.34.66-.37.62-.21.37-.17.32-.26.38-.12.24-.21.37-.21.33-.21.29-.25.33-.21.29-.42.66-.75.86-.51.54-.29.28-.25.29-.29.25-.92.69-.29.21-.38.16-.37.12-.33.08-.75.16h-.7l-.46,0L179,79l-.37-.13-.33-.21-.29-.25-.2-.29-.2-.33-.17-.38-.08-.33-.08-.37,0-.38V76l.09-.74.08-.37.13-.38.17-.74.13-.33.09-.37.12-.38.13-.32.38-1.12,0-.33.08-.37.13-.37.09-.37.08-.33.26-.75.13-.5.13-.53.25-.75.09-.37.08-.29.09-.37.17-.41.13-.33.25-1.12.13-.37.13-.49.17-.54.13-.37.17-.33.25-.21.37-.16.33,0,.42.05.74.09.66.25.21.29v.38l-.08.37-.13.49L184,64l-.26.74-.08.33-.09.38-.13.41-.12.49-.43,1.24-.09.38-.17.53-.29.87-.09.37-.09.33-.08.37-.3.7-.08.38-.3,1-.26.74-.08.37-.13.54-.13.66-.09.71.08.62.32.46.46.12.37,0,.37-.17.3-.2.33-.25,1.38-1.35.25-.29.21-.29.25-.33.42-.65.25-.29.17-.25.21-.33.25-.37.17-.37.34-.7.5-1,.21-.33.38-.2.53.08ZM182.2,57.12l.21-.33.33-.29.33-.2.42-.12.37-.08h.42l.37.09.33.21.29.25.28.29.21.33.12.38,0,.37v.42l-.12.37-.21.33-.26.33-.29.24-.33.25-.38.16-.41.08-.37-.05-.42-.08-.66-.42-.24-.29L182,59l-.08-.37,0-.37,0-.38.09-.41Z"/>
</g>
</svg>
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<defs>
<style>
.cls-1 {
fill: #b4b2bb;
}
</style>
</defs>
<title>Hipster</title>
<g>
<path class="cls-1" d="M7.76,14.3a1.1,1.1,0,1,0,1.1,1.1A1.1,1.1,0,0,0,7.76,14.3Zm5.5,0a1.1,1.1,0,1,0,1.1,1.1A1.1,1.1,0,0,0,13.26,14.3ZM7.85,12.51l0-.06.49-.9h4.1a1.1,1.1,0,0,0,1-.57l2.12-3.85-.95-.53h0L14,7.7H7.29L6.77,6.6,6.25,5.5H4.46V6.6h1.1l2,4.17-.75,1.35a1.19,1.19,0,0,0-.13.53,1.1,1.1,0,0,0,1.1,1.1h6.6v-1.1H8A.14.14,0,0,1,7.85,12.51Z"/>
<path class="cls-1" d="M10,2a8,8,0,1,1-8,8,8,8,0,0,1,8-8m0-2A10,10,0,1,0,20,10,10,10,0,0,0,10,0Z"/>
</g>
</svg>
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<defs>
<style>
.cls-1 {
fill: #b4b2bb;
}
</style>
</defs>
<title>Hipster</title>
<g>
<path class="cls-1" d="M14.5,5.5h-9A1.12,1.12,0,0,0,4.38,6.62v6.76A1.12,1.12,0,0,0,5.5,14.5h9a1.12,1.12,0,0,0,1.12-1.12V6.62A1.12,1.12,0,0,0,14.5,5.5Zm0,7.88h-9V10h9Zm0-5.63h-9V6.62h9Z"/>
<path class="cls-1" d="M10,2a8,8,0,1,1-8,8,8,8,0,0,1,8-8m0-2A10,10,0,1,0,20,10,10,10,0,0,0,10,0Z"/>
</g>
</svg>
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<defs>
<style>
.cls-1 {
fill: #605f64;
}
</style>
</defs>
<title>Hipster</title>
<g>
<path class="cls-1" d="M10.28,9.21c-1.64-.43-2.16-.87-2.16-1.56s.72-1.33,2-1.33,1.76.61,1.8,1.51h1.6a2.88,2.88,0,0,0-2.32-2.75V3.5H9V5.06A2.82,2.82,0,0,0,6.45,7.67c0,1.67,1.38,2.5,3.4,3,1.8.43,2.16,1.07,2.16,1.74,0,.5-.35,1.29-1.95,1.29S8,13,7.91,12.17H6.32A3,3,0,0,0,9,14.93V16.5h2.17V15c1.41-.27,2.53-1.09,2.53-2.57C13.68,10.33,11.92,9.63,10.28,9.21Z"/>
<path class="cls-1" d="M10,2a8,8,0,1,1-8,8,8,8,0,0,1,8-8m0-2A10,10,0,1,0,20,10,10,10,0,0,0,10,0Z"/>
</g>
</svg>