Showing preview only (333K chars total). Download the full file or copy to clipboard to get everything.
Repository: techschool/pcbook-go
Branch: master
Commit: aa74912a982c
Files: 78
Total size: 311.7 KB
Directory structure:
gitextract_gwqh_f95/
├── .github/
│ └── workflows/
│ └── ci.yml
├── Makefile
├── README.md
├── cert/
│ ├── ca-cert.pem
│ ├── ca-cert.srl
│ ├── ca-key.pem
│ ├── client-cert.pem
│ ├── client-ext.cnf
│ ├── client-key.pem
│ ├── client-req.pem
│ ├── gen.sh
│ ├── server-cert.pem
│ ├── server-ext.cnf
│ ├── server-key.pem
│ └── server-req.pem
├── client/
│ ├── auth_client.go
│ ├── auth_interceptor.go
│ └── laptop_client.go
├── cmd/
│ ├── client/
│ │ └── main.go
│ └── server/
│ └── main.go
├── go.mod
├── go.sum
├── img/
│ └── .gitkeep
├── nginx.conf
├── pb/
│ ├── auth_service.pb.go
│ ├── auth_service.pb.gw.go
│ ├── auth_service_grpc.pb.go
│ ├── filter_message.pb.go
│ ├── keyboard_message.pb.go
│ ├── laptop_message.pb.go
│ ├── laptop_service.pb.go
│ ├── laptop_service.pb.gw.go
│ ├── laptop_service_grpc.pb.go
│ ├── memory_message.pb.go
│ ├── processor_message.pb.go
│ ├── screen_message.pb.go
│ └── storage_message.pb.go
├── proto/
│ ├── auth_service.proto
│ ├── filter_message.proto
│ ├── google/
│ │ ├── api/
│ │ │ ├── annotations.proto
│ │ │ ├── http.proto
│ │ │ └── httpbody.proto
│ │ └── rpc/
│ │ ├── code.proto
│ │ ├── error_details.proto
│ │ └── status.proto
│ ├── keyboard_message.proto
│ ├── laptop_message.proto
│ ├── laptop_service.proto
│ ├── memory_message.proto
│ ├── processor_message.proto
│ ├── screen_message.proto
│ └── storage_message.proto
├── sample/
│ ├── laptop.go
│ └── random.go
├── serializer/
│ ├── file.go
│ ├── file_test.go
│ └── json.go
├── service/
│ ├── auth_interceptor.go
│ ├── auth_server.go
│ ├── image_store.go
│ ├── jwt_manager.go
│ ├── laptop_client_test.go
│ ├── laptop_server.go
│ ├── laptop_server_test.go
│ ├── laptop_store.go
│ ├── rating_store.go
│ ├── user.go
│ └── user_store.go
├── swagger/
│ ├── auth_service.swagger.json
│ ├── filter_message.swagger.json
│ ├── keyboard_message.swagger.json
│ ├── laptop_message.swagger.json
│ ├── laptop_service.swagger.json
│ ├── memory_message.swagger.json
│ ├── processor_message.swagger.json
│ ├── screen_message.swagger.json
│ └── storage_message.swagger.json
└── tmp/
└── laptop.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/ci.yml
================================================
name: ci-test
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.15
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Test
run: make test
================================================
FILE: Makefile
================================================
clean:
rm pb/*
rm swagger/*
gen:
protoc --proto_path=proto proto/*.proto --go_out=:pb --go-grpc_out=:pb --grpc-gateway_out=:pb --openapiv2_out=:swagger
server1:
go run cmd/server/main.go -port 50051
server2:
go run cmd/server/main.go -port 50052
server1-tls:
go run cmd/server/main.go -port 50051 -tls
server2-tls:
go run cmd/server/main.go -port 50052 -tls
server:
go run cmd/server/main.go -port 8080
server-tls:
go run cmd/server/main.go -port 8080 -tls
rest:
go run cmd/server/main.go -port 8081 -type rest -endpoint 0.0.0.0:8080
client:
go run cmd/client/main.go -address 0.0.0.0:8080
client-tls:
go run cmd/client/main.go -address 0.0.0.0:8080 -tls
test:
go test -cover -race ./...
cert:
cd cert; ./gen.sh; cd ..
.PHONY: clean gen server client test cert
================================================
FILE: README.md
================================================
# PC Book - Go
This repository contains the Golang codes for the hands-on section of [The complete gRPC course](http://bit.ly/grpccourse) by [TECH SCHOOL](https://dev.to/techschoolguru).

## The complete gRPC course
If you're building APIs for your microservices or mobile applications, you definitely want to try gRPC. It is super-fast, strongly-typed, and you no longer need to write a lot of boilerplate codes for services communication. Thanks to awesome HTTP/2 and Protocol Buffer!
This is a 4-in-1 course, where you will learn not only gRPC, but also protocol-buffer and backend development with Go and Java. The codes in this course are production-grade, with well-organised structure and unit tests.
### What you’ll learn
- What gRPC is, how it works, why we should use it, and where it is suitable to.
- The amazing HTTP/2 protocol that gRPC is built on.
- Compare gRPC with REST.
- Write and serialise protocol-buffer messages using Go + Java.
- Define gRPC services with protocol-buffer and generate Go + Java codes.
- Implement 4 types of gRPC using Go + Java: unary, server-streaming, client-streaming, bidirectional streaming.
- Handle context deadline, gRPC errors and status codes.
- Write production-grade application with interfaces and unit tests for gRPC services.
- Use gRPC interceptors to authenticate & authorise users with JWT.
- Secure gRPC connection with sever-side & mutual SSL/TLS.
- Enable gRPC reflections for service discovery.
### Are there any course requirements or prerequisites?
- You only need to have basic programming skills in Go or Java.
## The PC book application
PC book is an application to manage and search laptop configurations. It provides 4 gRPC APIs:
1. Create a new laptop: [unary gRPC](https://youtu.be/LOE_tkVFtb0)
This is a unary RPC API that allows client to create a new laptop with some specific configurations.
The input of the API is a laptop, and it returns the unique ID of the created laptop.
The laptop ID is a UUID, and can be set by the client, or randomly generated by the server if it's not provided.
2. Search laptops with some filtering conditions: [server-streaming gRPC](https://youtu.be/SBPjEbZcgf8)
This is a server-streaming RPC API that allows client to search for laptops that satisfies some filtering conditions, such as the maximum price, minimum cores, minimum CPU frequency, and minimum RAM.
The input of the API is the filtering conditions, and it returns a stream of laptops that satisfy the conditions.
3. Upload a laptop image file in chunks: [client-streaming gRPC](https://youtu.be/i9H3BaRGLEc)
This is a client-streaming RPC API that allows client to upload 1 laptop image file to the server. The file will be split into multiple chunks of 1 KB, and they will be sent to the server as a stream.
The input of the API is a stream of request, which can either be:
- Metadata of the image (only the 1st request): which contains the laptop ID, and the image type (or file extension) such as `.jpg` or `.png`.
- Or a binary data chunk of the image.
The total size of the image should not exceed 1 MB.
The API will returns a response that contains the uploaded image ID (random UUID generated by the server) and the total size of the image.
4. Rate multiple laptops and get back average rating for each of them: [bidirectional-streaming gRPC](https://youtu.be/hjTI35iKMyQ)
This is a bidirectional-streaming RPC API that allows client to rate multiple laptops, each with a score between 1 to 10, and get back the average rating score for each of them.
The input of the API is a stream of requests, each with a laptop ID and a score.
The API will returns a stream of responses, each contains a laptop ID, the number of times that laptop was rated, and the average rated score.
## Setup development environment
- Install `protoc`:
```bash
brew install protobuf
```
- Install `protoc-gen-go` and `protoc-gen-go-grpc`
```bash
go get google.golang.org/protobuf/cmd/protoc-gen-go
go get google.golang.org/grpc/cmd/protoc-gen-go-grpc
```
- Install `protoc-gen-grpc-gateway` and `protoc-gen-openapiv2`
```bash
go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
```
## How to run
- Generate codes from proto files:
```bash
make gen
```
- Clean up generated codes in `pb` and `swagger` folders:
```bash
make clean
```
- Run unit tests:
```bash
make test
```
- Run server and client:
```bash
make server
make client
```
- Generate SSL/TLS certificates:
```bash
make cert
```
## TECH SCHOOL - From noob to pro
At Tech School, we believe that everyone deserves a good and free education. The purpose of Tech School is to give everyone a chance to learn IT by giving free, high-quality tutorials and coding courses on Youtube.
New videos are uploaded every week. The video topics are wide-ranging, and suitable for many different levels of tech knowledge: from noob to pro. The most important thing is: all content created by Tech School is free and will always be free.
If you like the videos and want to support us with this vision, please share, subscribe, or [donate to us](https://donorbox.org/techschool). That would give us a lot of motivation to make more useful stuffs for the community. Thank you!
================================================
FILE: cert/ca-cert.pem
================================================
-----BEGIN CERTIFICATE-----
MIIFxjCCA64CCQDY35xYDFXtHjANBgkqhkiG9w0BAQsFADCBpDELMAkGA1UEBhMC
RlIxEjAQBgNVBAgMCU9jY2l0YW5pZTERMA8GA1UEBwwIVG91bG91c2UxFDASBgNV
BAoMC1RlY2ggU2Nob29sMRIwEAYDVQQLDAlFZHVjYXRpb24xGjAYBgNVBAMMESou
dGVjaHNjaG9vbC5ndXJ1MSgwJgYJKoZIhvcNAQkBFhl0ZWNoc2Nob29sLmd1cnVA
Z21haWwuY29tMB4XDTIwMDQxNTEwMjMwNVoXDTIxMDQxNTEwMjMwNVowgaQxCzAJ
BgNVBAYTAkZSMRIwEAYDVQQIDAlPY2NpdGFuaWUxETAPBgNVBAcMCFRvdWxvdXNl
MRQwEgYDVQQKDAtUZWNoIFNjaG9vbDESMBAGA1UECwwJRWR1Y2F0aW9uMRowGAYD
VQQDDBEqLnRlY2hzY2hvb2wuZ3VydTEoMCYGCSqGSIb3DQEJARYZdGVjaHNjaG9v
bC5ndXJ1QGdtYWlsLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
AMlfsjdzwr9baKYRiL1VmbTSMxnCH7kQFYULl1073UqfkYrWSu3P8yiVSVu/EzUG
wlN3C8wncRMn7JtBy3GuIjHnPC7t8E6ztcDWgear2RjzDQZmHVkcdAFji6hW2qEG
LDIKUA2wfRXbjXnRqMj4ZZyIN6cHUJgo4+ZKwMus39WnwuWxQ/QNQhH432lfCHjj
RiyA9AdJvObZVSUuHxfchbRR6aFFr8FL6/9hp5XTVfhz7iOEqWwXDwBQuBG8DHVt
zp7i4BXx0DuTRhV31KAjz1nEdUFFZZB7rwcySAeL9OquObD8x1hehqkFU8F5z5JA
O7nxWYOjTiRIVzLSwERi9TYAQbl8760jHlrn+0NDPAFXhsXmqYMYkNSJ486dNkT3
yDr6kDeb4+r3bsN6g4GnXkXSRFcYUGMZA2k5tDJZbNd0DPMRV1QKy0Hz8R3JIJnN
2bD+tQ0iS+iLpLO2kybQqnrU/1iJGju1Sg4VM5R9xOtMBlewpYOu+3gPimsDq+uP
jZg3GxQiBrfMBUJ35IlAHBw+yB/ObeEbcq3nZBQcetsVFIN3Qws6SlCxU3yFj+xk
/gDOSJ0pPIuNlC5x9Rf9tV4LHZizE16hnf9Z4GzBW3Wu9hFw7ESqI11c++q1Lvq0
b0Gou/TESjDlyoYE6ucKFz9I6ylqbjddCQFZl5u6AAF1AgMBAAEwDQYJKoZIhvcN
AQELBQADggIBAKOD7Peqs5+BgBtX9EWk08rt29ALuO9lxxffcsAKSOYYCUOlwom4
Uz2+l8hZgrLG631iQR+l9KzpbIt4V8c+kX+NUONGG6evSxLYev77hv2Z9cdOAfWF
sP4jgigcUsH6Zs6gEQ6PeBf/XqNnghu4i9dcmjdOiYj2hx7e9baBwvrqnC5foqcZ
NxqWkXZSidtD1iECIEJSIJYLwMdPy5cHVdAqyiFSjSWFDMccqvUIMOjIqyRbxEch
5UxGky7+3iS3r+UvTiloOkDDDOayYclc7CCBvknbLMnzWYcDoh+RiK4qQ/GWeEpr
Yq02Mg5h9C/phE6mZln3A0AgFwJ2mSzXJHy2zAbSbXybCzDmojcykq+44TxuFP6z
SXGzo6nkQ6om2BF0Z9GNlPFkaqMrBIo/6kctZlG1sptswlr5BkowbZEwLUAcji7k
kFzquWkZeOU1zQ1ZBDllajh6zWzJCnyR0AmRz8p7iI35XA1vHRYXsZlfVSjC3P5d
0AiyoyyuInAzAtqPZUKSRAKUFkwyVvC48p4T/GxhgViNM/mn+OS905dt9DtBzTAw
NkZ/SLYnRPpwGB7csw2EJgsTYRm5pg/QtA9pCmPib1IGT9SeLACJOMe+w0VAKuun
I4pOaolfVC5dclS0rMxwC1S1wBp4YWDbnrxNa6lHRb+FDZBNwBGbfjry
-----END CERTIFICATE-----
================================================
FILE: cert/ca-cert.srl
================================================
B141E873FD7B8575
================================================
FILE: cert/ca-key.pem
================================================
-----BEGIN PRIVATE KEY-----
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDJX7I3c8K/W2im
EYi9VZm00jMZwh+5EBWFC5ddO91Kn5GK1krtz/MolUlbvxM1BsJTdwvMJ3ETJ+yb
QctxriIx5zwu7fBOs7XA1oHmq9kY8w0GZh1ZHHQBY4uoVtqhBiwyClANsH0V2415
0ajI+GWciDenB1CYKOPmSsDLrN/Vp8LlsUP0DUIR+N9pXwh440YsgPQHSbzm2VUl
Lh8X3IW0UemhRa/BS+v/YaeV01X4c+4jhKlsFw8AULgRvAx1bc6e4uAV8dA7k0YV
d9SgI89ZxHVBRWWQe68HMkgHi/Tqrjmw/MdYXoapBVPBec+SQDu58VmDo04kSFcy
0sBEYvU2AEG5fO+tIx5a5/tDQzwBV4bF5qmDGJDUiePOnTZE98g6+pA3m+Pq927D
eoOBp15F0kRXGFBjGQNpObQyWWzXdAzzEVdUCstB8/EdySCZzdmw/rUNIkvoi6Sz
tpMm0Kp61P9YiRo7tUoOFTOUfcTrTAZXsKWDrvt4D4prA6vrj42YNxsUIga3zAVC
d+SJQBwcPsgfzm3hG3Kt52QUHHrbFRSDd0MLOkpQsVN8hY/sZP4AzkidKTyLjZQu
cfUX/bVeCx2YsxNeoZ3/WeBswVt1rvYRcOxEqiNdXPvqtS76tG9BqLv0xEow5cqG
BOrnChc/SOspam43XQkBWZebugABdQIDAQABAoICAQCVxKyhfWEsPOnaCVRvrIiC
6YrD75L0arf2maZb2zg8Ve1DGxnjQTQRzOYgbD32xC4nMXT+w57fpmPdHNQYmnAo
OViTdrexcQsOfvth+hGe8rWPOsc9DWJh3g1yiBZWiGa6WN0tMUP2y7GvFnW38rZv
8wehHFmesVq+Xn6BfPOEzh6wAmUN0AaBo11V2y5L6oy4cLgN65OpBZ7D5keN0Z9H
e1yNa2zKEJNW/uRLFEDuZhqJJBN1prirfV1JI1kIxUBU/1u2NoCurlwDf3oOGFQQ
6YJjpx9gk/ybF5RmuHrRR/70WSxR1wvEDYg7b0Mn/MnvA0eWFhD5/yuLSx9gPVEt
I5BIF/neUsEv5g9/T5H5hgLV5vs1wBOmeliGNBVT/harXtiztDgpd+Kja2f0B/+c
QkliGo3Iazxxo48cpKt+F3nVKxUtcMTKUgBFGWaS+uKR2dMA908oxh9vjL2aOEF7
YhtaXkl7vIAMouVWK0WXx5Mc6ks3gurUFMflmLslPvRmqAURYqz/kZNRqxZE0OZ2
rI/mVzck0zhp4PgKJIbRchL9Y8CgasgCPs2EF1y74Sw+cmN0PL9mk4keRDL+JnbZ
2a+57zHMqd3n1/w/lSy5BQZ0qvyJpc6wXlU+qKTbNp1FzODBcEE9Rj2j4i7yElvK
xPzkVnOWfite2Tf8+XOMwQKCAQEA90tOIaZNLyN/xJLS1au7u9q84zfjEOMvpqPK
BniPRshR27EKX11gOCi2F5qcdEgvV4TOdg/n++Xck7MZeXcrSvcCoiCDe0JjMC34
FW/o8376fma1mDQ7mlAIoYB22XfZidqany25pTxOJKZqEcsFYmUrJGUNZHoqjp3K
vnD8Xl7JYLTZBVDU8m//GSO2Zco1lp/wttzF/vg4I6nW8uj1v8Ery6YC32Q7U9cz
VhqeKnHOfXUOmb0YG9PCljudK1mJJ74ldpJ0uhIcKdMQQi5ccWu1kYgOu4JsAbCO
WlCS6bptG82ysv3iqr+Mg7vnckbGk0UMl3w4g4M29ua9KOgMuQKCAQEA0HaKvfbP
PiHa4TEt7iPJ010mAZmJnhpUPFz5sVRyJDJa5SPMXx3rwQb8+nq6sw/YzzGr2DEm
aYz0Csn66EHgilBUQyr2jhLGdtC2iWmDA9vxew9VRNOYyerkTwpEtQMGycIitv1F
1MomEWCh56T3JN58JwgjnG/O0D4IRSRsfJsBERlHlQObJ7hEdd+cuoRIJEsrQzxg
y3Z5HmFDAqLO0WOwoJV1SaNSxNwEa3GiEFydNuxgDpdUrCAl3y8wYXQQNqyQaZQw
lu78hk1rMf/jGkUS/y59CKrDbS9qBYjT55yS3czfsIodg7TsP8ePtHszyW4jh3jt
up6mHHG/hN/UnQKCAQEA15/Z6I1RD6EsbwJ2w8iSUSJRQO4iFz+A9RQru6izhUx1
09Fy8eRBWbZlz/8IHHw0i2NJgrgr1wB+bGrl83ttTFhE+4jOHFOumPv8LPT/chFt
6Xk1LhmdPtg6LlgNSWGvVPw/hjwge2sx19Mi+ZDEiR8dlwZlvw6mvOPpPFTYOJD9
lk0aTgBFLX9qN0lkaSz/vO6IvWmTWtakXLRisDtgzGpq/Y8rQg3rjRc/s/xRnUDO
g6XlrTesJddm/AfO61WOuhCaKeFZ1kSkOfPHYW17PYplLxgrgGQgOPjxpt5Ku3HK
YUviXR/y3F9Y7iSRkpsT2qWCbTPrMwDelDptBZYQQQKCAQAbXWRLGYoM8u7DnuwT
lbkZuOGTVi9dhMFIB0Bzyc0N+Vo7OB7M4aWf+iXdT50QgmUIldGkGJedRXaHsAny
0SsDnRXil1I0RjytPiqoESS0rfueFt4vocMtxlrgEU4BoPsUIxrhgI/ZJgwnPdMj
EGGtAlOz3/qkv3ybk3kMcoKXPNXAA9yEsCt+5E6AVrFBProloYR1WAiwzMWLemMM
hoi1retyuQvjdcAYvXULEaifkzjEC/V0FON1kObHzG8Ca/Tw6Ggwo9ZZCdg2XRVU
Q+3w9d5Phy+8ooXy4EV/on2GquQQn6NBjm/faTGWEcFIhN/AcmfRkctLMyZFF513
eNZ1AoIBADG8nW3c3sIWSIokw6NdI9TLMeQVqVSW2LC8K6L7ZDjl3Ypiu4fT1hBt
CvF3hdvAed+n8Hgb8+rclmubbIdhAVPYKvsuyMGP7fhb7vw1HOsfwSm8ovx+AGXK
siMDXDZKAvOAUcCnO5kPosTwfl3HJhbLArzl9AcU8wvSUphbL8NiJ2pdujs3863E
E9NqBbjd9AHak0EZ29CEI0MLX6/9ndjROjm4Hd1FpoQexm4mh+JnPhC++8aD65qA
pOnVnS+TOw3nGP6KHyorYEipzPjg+jFzsgQhup01Eqv8jZ++msHrgnj507Tf73Cp
uwawX4qaay9IGjuXdE8Py3mM3xpDXPA=
-----END PRIVATE KEY-----
================================================
FILE: cert/client-cert.pem
================================================
-----BEGIN CERTIFICATE-----
MIIF4jCCA8qgAwIBAgIJALFB6HP9e4V1MA0GCSqGSIb3DQEBBQUAMIGkMQswCQYD
VQQGEwJGUjESMBAGA1UECAwJT2NjaXRhbmllMREwDwYDVQQHDAhUb3Vsb3VzZTEU
MBIGA1UECgwLVGVjaCBTY2hvb2wxEjAQBgNVBAsMCUVkdWNhdGlvbjEaMBgGA1UE
AwwRKi50ZWNoc2Nob29sLmd1cnUxKDAmBgkqhkiG9w0BCQEWGXRlY2hzY2hvb2wu
Z3VydUBnbWFpbC5jb20wHhcNMjAwNDE1MTAyMzA4WhcNMjAwNjE0MTAyMzA4WjCB
ljELMAkGA1UEBhMCRlIxDzANBgNVBAgMBkFsc2FjZTETMBEGA1UEBwwKU3RyYXNi
b3VyZzESMBAGA1UECgwJUEMgQ2xpZW50MREwDwYDVQQLDAhDb21wdXRlcjEXMBUG
A1UEAwwOKi5wY2NsaWVudC5jb20xITAfBgkqhkiG9w0BCQEWEnBjY2xpZW50QGdt
YWlsLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAN1B/FRa+rT/
AQH6s5ON5GF3SnwyCv1ALnzwWb6AXFBKI8vx38JheqX8igqWyjOMzITO86YNQFhu
Ix18XsRRCOPG3lcCeR6n8/uu2VyEPUcNfRHGhs+JdmT3jZeokafwsCQfwK5A2ifY
qU3klElTwwVwD9HgTQOnqOgXEwzpC01EzIvQtR6/49ANOJUURfO8ae2TglXv90yT
BI8u4/lV2dKPWjmxsnUpadKhKSHGU5eoT3Dyg0KTig1pXYEI6aW+qBXW0B/loone
fnN2W/TvJ9u0E9ZOWEr8Ekpz7Cg4psZuGTf6PMvjEELCcm9pT/jAjOOqmKeZYU7m
zecsuzmEi4d3X5XsnDXd2LuZ3VFiW9sdp0RZDgWTF7J1MJ9kg7Lhc46zhtrLTqlB
FisSVMWGLvhpqjVTBUIWCuAeKxVkZgStVitzrkxk4Av5dYI5XJqDCswmEIWnPKSX
t4B8S0F1sYCWYd4+GD9zkCgxPSvCNsGMKraR4E3M+EcBREJUezxAvJN5yPur+08+
r0hsQC7p4LMTZlVLsBOACGALCfQkJhM1ycBNBC1AQsRkqnsVuydlqYTef8pSCDUp
qGoLkokoC2BfAVEzuHRS8PoNEX60lwU+pprCmGtbKQuFwQUX3FzyMWhtA9OSWrfD
zShb4C3slKu2pk/pw6J2fAdkxAe2wBBpAgMBAAGjIzAhMB8GA1UdEQQYMBaCDiou
cGNjbGllbnQuY29thwQAAAAAMA0GCSqGSIb3DQEBBQUAA4ICAQBsxrzqLj6WWqrn
QFr6fEsOiprIilwW1/de8ATnubbkItjJmRsdIrZHVDgnahVr+gPnggwS8R99h4gr
jalG11Fa3narO0CXldG2MGrnkU8AKuSu6dmwCBmKmZH5IhajcbhdRDuR3JOQBAn7
Yj4LZylG652Gq48hFY3bmM4/P4bKi+z7ZkoUq6iitt57Y66blfXsKUNwjtFxJEzv
figvXKq1ZetAuVNcmOROvYaFisyw5Yvk7XXBw/7DwCUScKBV71MOS6FrkQ/IQ/Xq
qrwD7qBacozUZ37sWULihyjJNuikDcUAVg74jcFSgohluSpbigxgXeDdWgwh8Q3Q
n3ts/ZOb0XDeUp4QAqOxUShUvVEsJGi8NCOWjpp/enzeaDJ85QgCVvK8McIxQgbu
i2IXmnHHzgc6PMpE79qOffeugtUCN/6odvveFq0rN3QJMKFU5mFjitWFfko2OVLv
/jMuJ00cISCGJFXIDij/XzetvwD0hGME9jUhp68xdfZDX1Tnc60gqSyJqaFg6iKa
0iSvy3ShR1k/VATsDP1DTQlon39dbOYPhsSkk1Lc4RSMJBgJ6lFum+9vd9/gVZEG
Jno5YIiGZphbVjE5/KQ3jtFL5WZOZHPk+FYMGxwey5h5nXN2veWhVCkwx9K4YaCB
9BhkA0M0G3zQoGqSv94DTeI32qaxNg==
-----END CERTIFICATE-----
================================================
FILE: cert/client-ext.cnf
================================================
subjectAltName=DNS:*.pcclient.com,IP:0.0.0.0
================================================
FILE: cert/client-key.pem
================================================
-----BEGIN PRIVATE KEY-----
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDdQfxUWvq0/wEB
+rOTjeRhd0p8Mgr9QC588Fm+gFxQSiPL8d/CYXql/IoKlsozjMyEzvOmDUBYbiMd
fF7EUQjjxt5XAnkep/P7rtlchD1HDX0RxobPiXZk942XqJGn8LAkH8CuQNon2KlN
5JRJU8MFcA/R4E0Dp6joFxMM6QtNRMyL0LUev+PQDTiVFEXzvGntk4JV7/dMkwSP
LuP5VdnSj1o5sbJ1KWnSoSkhxlOXqE9w8oNCk4oNaV2BCOmlvqgV1tAf5aKJ3n5z
dlv07yfbtBPWTlhK/BJKc+woOKbGbhk3+jzL4xBCwnJvaU/4wIzjqpinmWFO5s3n
LLs5hIuHd1+V7Jw13di7md1RYlvbHadEWQ4FkxeydTCfZIOy4XOOs4bay06pQRYr
ElTFhi74aao1UwVCFgrgHisVZGYErVYrc65MZOAL+XWCOVyagwrMJhCFpzykl7eA
fEtBdbGAlmHePhg/c5AoMT0rwjbBjCq2keBNzPhHAURCVHs8QLyTecj7q/tPPq9I
bEAu6eCzE2ZVS7ATgAhgCwn0JCYTNcnATQQtQELEZKp7FbsnZamE3n/KUgg1Kahq
C5KJKAtgXwFRM7h0UvD6DRF+tJcFPqaawphrWykLhcEFF9xc8jFobQPTklq3w80o
W+At7JSrtqZP6cOidnwHZMQHtsAQaQIDAQABAoICAH2jIINN/hqUyp+zGhFpewuV
T2hiijbwIPW1DWDNRp4Y22bNe7/G1nw2gLQul7bZ9rBbS6M41xbfw3TU0IMteJzO
qiZCM0CjIjoCOU79kEYudJyJXLewWNhQcchyYfM5CuwYU7MfBEGoF8sxRrq0o4MM
9Q66DUFMDO9tWtXz5wUDUhr6cj55vATB3SVaE7apgIT1RAdEceq7eNVNTQqiI0Qb
PqKQMsOwtnRyKwcQtRri6ek67Cn72WJwODYzN2l0b8Gm7xuNq9QZ0TgDN4hH3Rw2
jyUb66r4o/I/DRRxxtHaZtuQbsFfuDYQcCavaEfaHqaQkopo4AaLrNPeZJnul8NP
whnKwydsrF40bajjIgQ7hFas/fy5toQPI501gTIGkXAWg8T2+qmFuxGqIAwGajBt
3bPJ+jbo+c3VZg4xS7yTLaa1EJcVKR60wkGxiJH0qDI0ly8WgUlxe1S+Q4WrloaK
y4kchI83zKH2HplFF2YdeUoP2taxWpZAfWOoC0YgTR5BmxVoK6lVpd/zZ3QWP0rh
0Lx4XTtlVphgYC3EV3ue5dmFo7Q0hnYIgbdRyW9J4ODmszcrRwqwyTx/v4oTmHb0
FKrsjSpVkvxB3ZMZP5En5bKzsTMneu0IaLhQrXNeUEVwTH9vDSnXX0ugCdDL7vKV
GaFcl9Ns8i6hW9X2Kk3ZAoIBAQD9oAmjo8mA8jStVAo3PvzpR2TjQFg/m5QqhmhB
ju1ZJhBlcW+NRUBKv3FxgtdsRp+eSLVtc5BeryMSHvN1ertXfmfUfdihMrKmJ9Gn
MjxbyqXnBREe8ALrNNjYNgXzviBNunxNaNjS7F/niAvHG93S7Bl3jy7nOy4VyxPs
7CkkcaYIJ3octTMkC+t00MPba6Ya4doUmpmgPWtiX3rHktn1xYVmXueWs6/Fyvfk
cAXsMxnjsFhw3LneILiYBW32d4+p4L7X3vhL4j7mbMYXf5XqwBOg3eWPVODpqVGU
iGFSOAC4CUtvrGIzFQ0tCbjA9w8OXdd6xu4JzdxAyge0JAFXAoIBAQDfVFxGykNW
QbX1PwP+v/n/3nmgSM07zF8xFy2tSu3YhF7eIje56zGDhaGVlN6wU0Gqm5bgENeL
FFBSLIzBw9Qi2mgRxd2tXB79v3swukhhGmCFVwSOWbPGQrDuOXHU1EEHmq8xRMo4
mc8s9nCJotOe1TN5BcbUVuPRu+9zW2lEhuxoMn9ZhtiHOUop+TJqb3wMICr4K137
dfICtb25DK6M5r5Es9DP1G6e2OjiH40Kkd+/vsxZu2gzIxyGcOcqde20yS+ihm76
yjPKkwV5s2HLFRv1hiOc0PUNqzLWC1pMEKiEqPmBtIh3mj5vq6ZmL7UXedT4V2my
tm0n5PtqOKQ/AoIBAQCY/any4UETHIe0KqbC7qcHXT65ar4RGJtHD67iJQJ9rV1k
pAnDcQu4S0V2UJP8R5nPlFKExJpI02LXcn4v1qodvC2L26IKkxd67TgloEMSp+pt
sfvC6ssH8OgBfI0YnA7GdIC4/U8V5OpxMvrPz7p+mlc+bMvBRkylbswFNewXhMq/
znh1ysQfsWUGIUyUFpqrSqQPm7aiF4qoW6onqyj5fX3b49HVcWzNZoMkdILOGYE7
fMvMwQkJujk/0r6jVzn9Iopck665r697tg/Eav0XD2iHuHLahDvsF2wTqjTysL+W
RF0R7y2JXOCG0390P1QAuZDbChbbKSf8mSIOg02fAoIBAQDAo9ExEvmApw/gq2mz
zj9EsdAyLXozEbgu7TJuX8rIUG5QqC1vhuvf6l4WXCK28CodkzZSstRqWKxsJZeI
8HXFVqYcZpQwHN1yvj/yKU2TzR/jBMueSswiwZZC93Q0RJ6Pg6OJGTBiIHKv8yfh
4X0vbfKHey8mLIk5eiYzWG92N/gmbSCixglyoz1Q9W7ClsXm47yM80OPTA7kvYYY
4FKUodkQBBejnjeJd8tyegq8SlY53MgCwwA/1BKf+TW9z5mqrzwSsml6lP6Vx7oa
X1yExAGpCPshIrGvB7TDI2nRYTErtWH7uxFYMcmXo/XWAWLxDBtj2GsJSAjiN8eS
uacbAoIBAFTcrGjSRo/v8DT+r8z5BClwuBmnsRWzTNx3ay/EMnLdGv2Jcg5I+p7l
VjioNmz/mF7Ff94nH0VohDrsbmKlVWs8zOxiotG/UUhgHfp2MX1OTxXzxwbxx+sB
Ekb7WuZ8yxWI7WboH5r4ENla3SeQb1HETNDhJoqVCi67XGkq5rY4DlNXtZQZdkzB
SH0c0JVykXk265qsvpthKObTakb92azMCdToipl0bdwRWwzjLlNV1cqJHdtaD40Z
0u8CfN8S2w7nwGIcLLWQVbN1nx7nspFmbo2kezu62YHpGh+hCvwGWTLelK6lAQWS
ovQGWC8qf6sde8JLYDVa3WC36B1OwTQ=
-----END PRIVATE KEY-----
================================================
FILE: cert/client-req.pem
================================================
-----BEGIN CERTIFICATE REQUEST-----
MIIE3DCCAsQCAQAwgZYxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZBbHNhY2UxEzAR
BgNVBAcMClN0cmFzYm91cmcxEjAQBgNVBAoMCVBDIENsaWVudDERMA8GA1UECwwI
Q29tcHV0ZXIxFzAVBgNVBAMMDioucGNjbGllbnQuY29tMSEwHwYJKoZIhvcNAQkB
FhJwY2NsaWVudEBnbWFpbC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
AoICAQDdQfxUWvq0/wEB+rOTjeRhd0p8Mgr9QC588Fm+gFxQSiPL8d/CYXql/IoK
lsozjMyEzvOmDUBYbiMdfF7EUQjjxt5XAnkep/P7rtlchD1HDX0RxobPiXZk942X
qJGn8LAkH8CuQNon2KlN5JRJU8MFcA/R4E0Dp6joFxMM6QtNRMyL0LUev+PQDTiV
FEXzvGntk4JV7/dMkwSPLuP5VdnSj1o5sbJ1KWnSoSkhxlOXqE9w8oNCk4oNaV2B
COmlvqgV1tAf5aKJ3n5zdlv07yfbtBPWTlhK/BJKc+woOKbGbhk3+jzL4xBCwnJv
aU/4wIzjqpinmWFO5s3nLLs5hIuHd1+V7Jw13di7md1RYlvbHadEWQ4FkxeydTCf
ZIOy4XOOs4bay06pQRYrElTFhi74aao1UwVCFgrgHisVZGYErVYrc65MZOAL+XWC
OVyagwrMJhCFpzykl7eAfEtBdbGAlmHePhg/c5AoMT0rwjbBjCq2keBNzPhHAURC
VHs8QLyTecj7q/tPPq9IbEAu6eCzE2ZVS7ATgAhgCwn0JCYTNcnATQQtQELEZKp7
FbsnZamE3n/KUgg1KahqC5KJKAtgXwFRM7h0UvD6DRF+tJcFPqaawphrWykLhcEF
F9xc8jFobQPTklq3w80oW+At7JSrtqZP6cOidnwHZMQHtsAQaQIDAQABoAAwDQYJ
KoZIhvcNAQELBQADggIBAHUPxGmovTlpVp6d9tOv2RbrqOq/9XDrul6O21/wsU0A
ZWlDyIHCrxjlTg8YrrHl1tiJYpi03pb707j6pjX6Q/AWLrTHuLo8l2cDnDu+xL08
SWZ20DtmM5GnYdmJzjY6mR6b5lYDrGlqFaynKCBn2IgB0AJeraGSsh/+cnhOgzya
6nKm8bOM9DSkcuki5b9JTYjtnmSUlwaaup0rlkKtnt0XLV4jKcQL4DurYfSXUXgs
sazbKj/N2xkRiSyk40lf5ASPFAyXDOr57c+IMKokhcWZvZunZc+reqWXkwvJQwZ9
8UNsrHmNopDbQI1mLk4Ky8cPRWbtdyjnJlwPc59TbGmdVNWm6KMmCwXqiegORivo
fwhOPEXvTusrcwgyREtS+bYOG0sFVGce6nxcIjBf9sY+igXGUTm9UyQVGO0YDLpJ
hJLL5bb9iv4nurokFWuoGI0H3XpeiLXBO6oPA/PXSEru6deP9/HwtGADVcoxQFa0
fLn9bA7lyyIXm6UpQXIAMv/Ptqv7v0SoesrwpxloJQKa43Iv0CkaFrWfLedCdayR
BgqOMvFcN6pzfCnaEpFb/CppBPP7Q/wVhAuIlmVq7M75q6/rW819RLxZFaNF0Yyx
0P5n1b8sSlUuQPPG0JNHGDZbM8Jz7iKMhcJuH8CQGI3EqPJVM3onvlYV1AWDKWI3
-----END CERTIFICATE REQUEST-----
================================================
FILE: cert/gen.sh
================================================
rm *.pem
# 1. Generate CA's private key and self-signed certificate
openssl req -x509 -newkey rsa:4096 -days 365 -nodes -keyout ca-key.pem -out ca-cert.pem -subj "/C=FR/ST=Occitanie/L=Toulouse/O=Tech School/OU=Education/CN=*.techschool.guru/emailAddress=techschool.guru@gmail.com"
echo "CA's self-signed certificate"
openssl x509 -in ca-cert.pem -noout -text
# 2. Generate web server's private key and certificate signing request (CSR)
openssl req -newkey rsa:4096 -nodes -keyout server-key.pem -out server-req.pem -subj "/C=FR/ST=Ile de France/L=Paris/O=PC Book/OU=Computer/CN=*.pcbook.com/emailAddress=pcbook@gmail.com"
# 3. Use CA's private key to sign web server's CSR and get back the signed certificate
openssl x509 -req -in server-req.pem -days 60 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile server-ext.cnf
echo "Server's signed certificate"
openssl x509 -in server-cert.pem -noout -text
# 4. Generate client's private key and certificate signing request (CSR)
openssl req -newkey rsa:4096 -nodes -keyout client-key.pem -out client-req.pem -subj "/C=FR/ST=Alsace/L=Strasbourg/O=PC Client/OU=Computer/CN=*.pcclient.com/emailAddress=pcclient@gmail.com"
# 5. Use CA's private key to sign client's CSR and get back the signed certificate
openssl x509 -req -in client-req.pem -days 60 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -extfile client-ext.cnf
echo "Client's signed certificate"
openssl x509 -in client-cert.pem -noout -text
================================================
FILE: cert/server-cert.pem
================================================
-----BEGIN CERTIFICATE-----
MIIF6jCCA9KgAwIBAgIJALFB6HP9e4V0MA0GCSqGSIb3DQEBBQUAMIGkMQswCQYD
VQQGEwJGUjESMBAGA1UECAwJT2NjaXRhbmllMREwDwYDVQQHDAhUb3Vsb3VzZTEU
MBIGA1UECgwLVGVjaCBTY2hvb2wxEjAQBgNVBAsMCUVkdWNhdGlvbjEaMBgGA1UE
AwwRKi50ZWNoc2Nob29sLmd1cnUxKDAmBgkqhkiG9w0BCQEWGXRlY2hzY2hvb2wu
Z3VydUBnbWFpbC5jb20wHhcNMjAwNDE1MTAyMzA3WhcNMjAwNjE0MTAyMzA3WjCB
kjELMAkGA1UEBhMCRlIxFjAUBgNVBAgMDUlsZSBkZSBGcmFuY2UxDjAMBgNVBAcM
BVBhcmlzMRAwDgYDVQQKDAdQQyBCb29rMREwDwYDVQQLDAhDb21wdXRlcjEVMBMG
A1UEAwwMKi5wY2Jvb2suY29tMR8wHQYJKoZIhvcNAQkBFhBwY2Jvb2tAZ21haWwu
Y29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwOsO3r/3ul2O2W1k
ka9j7VYLmXcBOY3Lkoo+k4N6dwLXH9NADO5cBQsLFyljHZ+gwbeV0pRDTs/PFwNA
ovHToNA6I2Uw9TI3Yz/MzUlZ4PpWkhdpYEnXWOgccXeKTFyYX4oKCGiTYLyDV7DH
E9kdMPX+sz7aiayloUKzOEVdLFtUIH2V8e9U5j7zKWAGoPCqbWYRGoAG6y8i3udi
6pS/7ETq0MVI+QXcQ8+eOrzNAZjkagMhEKB1czLFh7bb3YtHz/fl/Sujqn21oKWI
Y8CAHuMxYFMZO6im0QkztiL35vRPyozhi+Kr2LIaN4mfCKBjps13uGvYS8fDZbDD
+F8ix/Avhbz4PWEm2S5QdDSz44/69sbFKLk3qqoz0tO4byu5ADjIsnba9/9ZeqNx
3IiIXkPKMfNqfgq1Ti3M90aWW2uPF96AXWc/MKKHErA/AqgOn8XTBjzi/VBenoHH
NrsNoz0j5wV7i5SBPAGEOu5s7jV7hc5B5geWIpLOklUzryGiv5IRsM3U/dV9qYry
5GPywW0usxyyUKvTCe/GLt+63h+0xdGTbPs4Rd0twX0V1ZOpzMjnpaYtmczl+x8S
R0ZsTzyLhXsCzUPY5yNuGBNKIXBtwedZCEIZ3vT23lzvEgagUhqkymocVi9lXL+Z
U8I6Ketb4FHIjVtvCCZj8FVvHE0CAwEAAaMvMC0wKwYDVR0RBCQwIoIMKi5wY2Jv
b2suY29tggwqLnBjYm9vay5vcmeHBAAAAAAwDQYJKoZIhvcNAQEFBQADggIBABmv
Ce/pzmsilW9rFKPnZyr4zjdevi3zK4hn78iT2eCMoH48UigoFERphtqtnoinmHQD
qMFRfJ7ZBx6wPYo/fgxp+sXjMKT+hWUtU2CNQoVbeH2dpKU7xeyh82Q7fesajIYi
UrpuBlYBjZywNPJrpSKJyaq4H37Yt60SCA8GUrXb5LHcurRSJNtIQ8muOVgwvjAY
1mzADfOW2wlVX84oyXBHFo+3iXvjKhp8AahTCiQak4MvJwMPuiUJf8qIaqNi1w0s
Ot5p4QtLECYrfJxtsmyGRCOrCWdXpj2oPY85bz0CMdf7IuufFoTarhBm1E71YhOl
Sgrnj3w89HxIYDG/DvaybXO4/bs62oyQzcLzgeyoJeRLp23LpSR+8o4OV9koKUyQ
DBMNikKIqk+pZWEiJ6uILYUH1Ay8BBkUt/XY5Eeuy5RPtBrPJENHNAwgN5HU+h5i
glOc/rCpgYWWIVeHeickMxr3lZXVel9viNAucmLu9OuKi/jHksJcqimMDAwZGlnj
waeLHv1Ea/DX24lUkuA2m5w9RCcNI2ZmTmL7svwZrkdNmLLkcqz2nWBFyNZC5+P3
pN4Qe/thzJWsss1JB/Kn6V/2NX2/yr6eKrjt8jo5rucUbdtysOYrjCMBm0RiCJbK
3I3Nv1KsekkLnFiQIW7uXwLl5FJcaXHLfvYZlusV
-----END CERTIFICATE-----
================================================
FILE: cert/server-ext.cnf
================================================
subjectAltName=DNS:*.pcbook.com,DNS:*.pcbook.org,IP:0.0.0.0
================================================
FILE: cert/server-key.pem
================================================
-----BEGIN PRIVATE KEY-----
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDA6w7ev/e6XY7Z
bWSRr2PtVguZdwE5jcuSij6Tg3p3Atcf00AM7lwFCwsXKWMdn6DBt5XSlENOz88X
A0Ci8dOg0DojZTD1MjdjP8zNSVng+laSF2lgSddY6Bxxd4pMXJhfigoIaJNgvINX
sMcT2R0w9f6zPtqJrKWhQrM4RV0sW1QgfZXx71TmPvMpYAag8KptZhEagAbrLyLe
52LqlL/sROrQxUj5BdxDz546vM0BmORqAyEQoHVzMsWHttvdi0fP9+X9K6OqfbWg
pYhjwIAe4zFgUxk7qKbRCTO2Ivfm9E/KjOGL4qvYsho3iZ8IoGOmzXe4a9hLx8Nl
sMP4XyLH8C+FvPg9YSbZLlB0NLPjj/r2xsUouTeqqjPS07hvK7kAOMiydtr3/1l6
o3HciIheQ8ox82p+CrVOLcz3RpZba48X3oBdZz8woocSsD8CqA6fxdMGPOL9UF6e
gcc2uw2jPSPnBXuLlIE8AYQ67mzuNXuFzkHmB5Yiks6SVTOvIaK/khGwzdT91X2p
ivLkY/LBbS6zHLJQq9MJ78Yu37reH7TF0ZNs+zhF3S3BfRXVk6nMyOelpi2ZzOX7
HxJHRmxPPIuFewLNQ9jnI24YE0ohcG3B51kIQhne9PbeXO8SBqBSGqTKahxWL2Vc
v5lTwjop61vgUciNW28IJmPwVW8cTQIDAQABAoICAQCQuYZdSuxAbmF08aEJvecc
LHnlNibAE4TNuVI6fd8ImyPhpywcx1BXJDK8vHqzxYXm7Z/C6yEXZcR5AiKiWwKl
WLDUztwMhhCRL1KoCsgXhBYf4NpXtu2LsA1uffxNTwWsXrUqG7G8V4+84Exosm84
xMK/m3582/0hXhVvOHIujZEuEqjDaAVr+XuX5Ybzg7iG+5QHKlaGZsUlLbbCPrdA
O29hES+uSVw1rvKIJA0zjoyEjzZl78pMkqEnL+H/cLZ96P4rkGpmw4nXK3eHRemX
wl7PYWfDnsEOfnXBxLfvFgcp78hglbrPhMUwNtkMsq4ve2K+AoGwT/thNVu+3zgK
Mj/L+QSOKW7uY+E5oaETy7lg5P+65++4/iGyuszp2zX/iPMJcYwDoYcIwmIYkyIZ
nM5RNNCFoPAShKmkoboRh9KmVnzvoYPIpvYnNKGmQ/UCFxRm+l7dF9hrY+ZEYGcn
bF1nhKW8/i/GsVVvWOSN1NUdqZG80DwXNBruiKI171xPDoeEF+tlBaxz4Vk8F+yc
01gwAZnMMdF/3DPODmEEE40WFzSRy/HgzSQoLFFRpMU945S+LrR/1nzOFHgHubgz
stlp/oeV5IXZXbe3hnfWmfGSgEw7WEAlEvsofna/6REigNrBWsaZzKTlGlYuc1JK
ZgHoPjrwrbZgkYWH5fQfIQKCAQEA65PIIW4RhuvaWXPtuojNm0RHN4W0tvrkfhrf
KwnUM7atCqLHpf7doBJzpGSo3Q8vcaAhkvmINKVXogWV/mKulFE3QepcTjEpQNiQ
STrRm/Qg/Jv9zmpDYddtuVm3sHqfmONmsIBuMv/hPGxbuKr2x4lQZPI68wth0/0b
gxkNVF3JAksTyDpe7Zr0QEAKFiBwptTDnnZ5YdtiN3E1IwWle2FIa0AD8GAk/LH4
l/1aavgh9imEzbGqvlu8qU86LrPNfVjRUMe1Hk9Mpe8D9BuL6kk/Gx7b4bl+ObLG
wiIH+AVJa8RE3k7joqgmrVDGfL8q3SFyiNV/msyo0yLSY4bORQKCAQEA0aSIt14/
642yzO2TTtO9+EThG2PMV14sAWWWp6XRWtPUACmaCuI7Daz/taeymT2EiHx6x7pU
Rw4LZrhXPbjI0X4GuH0VSxYWnP1rgNqiqkTBMe9JNmNmweGHr3Ok7HMDX5QMKhxX
nFRYpRczrkSa87E5Js+jPRwiUUizOpfl5TsEAxS1kgcg+FJLqh2SfSOA8dBPArch
4W3O0L/E1AuLhfVUQLkTfUjQQJVVaZ2E3pWBLyGya10UbAcOlfi5MxFrK1M7gSRv
yMrk4l7N+68rZEk9DR93/p0C3B7kKB8lVQDfsaqnlMo7VXwG0oHTAsExV8JgPwQm
DMkkU2JPI0OaaQKCAQBkc0JuBsoQdvdHF2iyFm1dnJKleSzirT7LCthIOMu0NVu5
4kkxXejQva1z1rwubrAzSi2mxyIuGKayXqFjtF5uvebLA4zShqHpla6Imz0Pu9xo
+ncSEjujN8IAu+HYraDqB2UdM9ZJhtRa+HVv2+6YjNOsB6HdSugvBYk6sG7/n3H7
uVm5EjKyLFWkI+ppHvIKIUU8h5YghPRvYaVfxqOWZZgEq2pCkCyVV6oB3TU10ZJh
rbiEIRMGUoWyyCauDVs87KdsQ4vWXcf4JV/RMgHKJ+txvAnUSU0qezHHS82ME20I
N8uJ46erDvpXAs9wF+/GFOIKuMbNkiEWzo1ZhPzlAoIBAEL8rQbSoeAVlfVvUGuW
sxP6hmdnGysrlyoXGO2WyW+ZUht/L46cvTvgdJDJ9gKLKqcmB2F8g2N09GWtL4s0
WU6/U0xuA3jLpQwi2dABjIqVj5nyGNW9K192PhHtBNzc304SE1T9W21DclPGNyhP
GagWj+l73XAwZjLM5SAq2zXFBsIpQt9XUcynFzBTZLSBvLkH08dNVxEeMkB3lmAf
FEUIoBRSTwzwUELitLkbsRIieXXi8Yzm4BiopJt9L0hHH5RncxMP3nwtgLdoja8H
SPkxgcWIsaH0764AXO0JDre7oL63hfbAK/djuxZWj2NI8ghVvsVEARiCyQ2v0xO0
jUkCggEBALfx/VF1oYXVdpdHLfFZ0A7qgrVOpFa+mwzoSUx20/x9KIPsaKU0Rpc4
rRcdyGOqOm8ScQacpxkXqyh/akhG7WQysxp0EGof5IReWJJTTdlzZO0L5FN/EIrH
mLEojmA5xs54De6ywWPxmOsnk2jxYaGfUzVMzvBaJSkTLfIr/JGIsZMP590L4MCC
q10rQqmt+I5HZlsdDW908ThT1VwglRW6kQskxaEIsY1vOqi8q9AvrVNjSlga8Jp3
jrNe+80SA3nglFU16x7t7BkcrjTeE8zeuwRzzt98xHJSto6QRS2PWwCwGeGnyO6s
mQ46mZhKvL1F0M1v7dIRGpBcXSwHnIQ=
-----END PRIVATE KEY-----
================================================
FILE: cert/server-req.pem
================================================
-----BEGIN CERTIFICATE REQUEST-----
MIIE2DCCAsACAQAwgZIxCzAJBgNVBAYTAkZSMRYwFAYDVQQIDA1JbGUgZGUgRnJh
bmNlMQ4wDAYDVQQHDAVQYXJpczEQMA4GA1UECgwHUEMgQm9vazERMA8GA1UECwwI
Q29tcHV0ZXIxFTATBgNVBAMMDCoucGNib29rLmNvbTEfMB0GCSqGSIb3DQEJARYQ
cGNib29rQGdtYWlsLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
AMDrDt6/97pdjtltZJGvY+1WC5l3ATmNy5KKPpODencC1x/TQAzuXAULCxcpYx2f
oMG3ldKUQ07PzxcDQKLx06DQOiNlMPUyN2M/zM1JWeD6VpIXaWBJ11joHHF3ikxc
mF+KCghok2C8g1ewxxPZHTD1/rM+2omspaFCszhFXSxbVCB9lfHvVOY+8ylgBqDw
qm1mERqABusvIt7nYuqUv+xE6tDFSPkF3EPPnjq8zQGY5GoDIRCgdXMyxYe2292L
R8/35f0ro6p9taCliGPAgB7jMWBTGTuoptEJM7Yi9+b0T8qM4Yviq9iyGjeJnwig
Y6bNd7hr2EvHw2Www/hfIsfwL4W8+D1hJtkuUHQ0s+OP+vbGxSi5N6qqM9LTuG8r
uQA4yLJ22vf/WXqjcdyIiF5DyjHzan4KtU4tzPdGlltrjxfegF1nPzCihxKwPwKo
Dp/F0wY84v1QXp6Bxza7DaM9I+cFe4uUgTwBhDrubO41e4XOQeYHliKSzpJVM68h
or+SEbDN1P3VfamK8uRj8sFtLrMcslCr0wnvxi7fut4ftMXRk2z7OEXdLcF9FdWT
qczI56WmLZnM5fsfEkdGbE88i4V7As1D2OcjbhgTSiFwbcHnWQhCGd709t5c7xIG
oFIapMpqHFYvZVy/mVPCOinrW+BRyI1bbwgmY/BVbxxNAgMBAAGgADANBgkqhkiG
9w0BAQsFAAOCAgEAH+8i1ADYuh3KgEFmEOgmhBe2waanpC7bBOaPCuLlXOhJcZnb
TPTPVx9zBShPuaQS+xgobpRxBlataHKw2a/YoO8lPklglAcR188uRToIHjD/oeEa
nAwOE+FZHcxj7lkEWTjKTFlCNkEuWYm2QqEpYZ9jTRw23JyU6zHHZU9TRPRBNReL
hudzJOB4ZN+DZOOvhEUEOxNhVJDvPo9jldS7Ha0Xg8Q7AMxbmc7LYFx11/f2Oejv
PJL3HYi2WGRp2Ie81Heu8CgX5KEt6gu8EbLmTopQsVcU9CirO5klgFtJf3YzAMYz
4jZqbwR3N2WYGvloT2DrMvMhX4m+d0eC8I5M7JIW+GzUO7h4szvhSJ2Vw9c1rcGP
g6Y6RxEyG/GJtaG3SII8M+nXbPG4D/ZDYlh4YP0wWxeQZimifpAPmVpYlUG1nKgC
erHoOIw1INI9M5jgbFNEcTE/GLqficWjypq6lBeV5aZo/rXgyQFoxHI1N2lRbVfN
dEA+2D89le6VCizjHIsTDyY9tqGkRopsvm78DEwSmCBHnxRiky9A4MTRApAKoJDJ
Q/7AxbY7rhcWmwn+GZDoP5aY1aLe86Y1w3QR2VWKeXOKQeepRsOs8QTAPJoowpdy
fWlZKRZdDjhiwTCNztFL72KV7x0DcLVowYRJfrrK0MQdoosBs2DR74bztEg=
-----END CERTIFICATE REQUEST-----
================================================
FILE: client/auth_client.go
================================================
package client
import (
"context"
"time"
"gitlab.com/techschool/pcbook/pb"
"google.golang.org/grpc"
)
// AuthClient is a client to call authentication RPC
type AuthClient struct {
service pb.AuthServiceClient
username string
password string
}
// NewAuthClient returns a new auth client
func NewAuthClient(cc *grpc.ClientConn, username string, password string) *AuthClient {
service := pb.NewAuthServiceClient(cc)
return &AuthClient{service, username, password}
}
// Login login user and returns the access token
func (client *AuthClient) Login() (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
req := &pb.LoginRequest{
Username: client.username,
Password: client.password,
}
res, err := client.service.Login(ctx, req)
if err != nil {
return "", err
}
return res.GetAccessToken(), nil
}
================================================
FILE: client/auth_interceptor.go
================================================
package client
import (
"context"
"log"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
// AuthInterceptor is a client interceptor for authentication
type AuthInterceptor struct {
authClient *AuthClient
authMethods map[string]bool
accessToken string
}
// NewAuthInterceptor returns a new auth interceptor
func NewAuthInterceptor(
authClient *AuthClient,
authMethods map[string]bool,
refreshDuration time.Duration,
) (*AuthInterceptor, error) {
interceptor := &AuthInterceptor{
authClient: authClient,
authMethods: authMethods,
}
err := interceptor.scheduleRefreshToken(refreshDuration)
if err != nil {
return nil, err
}
return interceptor, nil
}
// Unary returns a client interceptor to authenticate unary RPC
func (interceptor *AuthInterceptor) Unary() grpc.UnaryClientInterceptor {
return func(
ctx context.Context,
method string,
req, reply interface{},
cc *grpc.ClientConn,
invoker grpc.UnaryInvoker,
opts ...grpc.CallOption,
) error {
log.Printf("--> unary interceptor: %s", method)
if interceptor.authMethods[method] {
return invoker(interceptor.attachToken(ctx), method, req, reply, cc, opts...)
}
return invoker(ctx, method, req, reply, cc, opts...)
}
}
// Stream returns a client interceptor to authenticate stream RPC
func (interceptor *AuthInterceptor) Stream() grpc.StreamClientInterceptor {
return func(
ctx context.Context,
desc *grpc.StreamDesc,
cc *grpc.ClientConn,
method string,
streamer grpc.Streamer,
opts ...grpc.CallOption,
) (grpc.ClientStream, error) {
log.Printf("--> stream interceptor: %s", method)
if interceptor.authMethods[method] {
return streamer(interceptor.attachToken(ctx), desc, cc, method, opts...)
}
return streamer(ctx, desc, cc, method, opts...)
}
}
func (interceptor *AuthInterceptor) attachToken(ctx context.Context) context.Context {
return metadata.AppendToOutgoingContext(ctx, "authorization", interceptor.accessToken)
}
func (interceptor *AuthInterceptor) scheduleRefreshToken(refreshDuration time.Duration) error {
err := interceptor.refreshToken()
if err != nil {
return err
}
go func() {
wait := refreshDuration
for {
time.Sleep(wait)
err := interceptor.refreshToken()
if err != nil {
wait = time.Second
} else {
wait = refreshDuration
}
}
}()
return nil
}
func (interceptor *AuthInterceptor) refreshToken() error {
accessToken, err := interceptor.authClient.Login()
if err != nil {
return err
}
interceptor.accessToken = accessToken
log.Printf("token refreshed: %v", accessToken)
return nil
}
================================================
FILE: client/laptop_client.go
================================================
package client
import (
"bufio"
"context"
"fmt"
"io"
"log"
"os"
"path/filepath"
"time"
"gitlab.com/techschool/pcbook/pb"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// LaptopClient is a client to call laptop service RPCs
type LaptopClient struct {
service pb.LaptopServiceClient
}
// NewLaptopClient returns a new laptop client
func NewLaptopClient(cc *grpc.ClientConn) *LaptopClient {
service := pb.NewLaptopServiceClient(cc)
return &LaptopClient{service}
}
// CreateLaptop calls create laptop RPC
func (laptopClient *LaptopClient) CreateLaptop(laptop *pb.Laptop) {
req := &pb.CreateLaptopRequest{
Laptop: laptop,
}
// set timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
res, err := laptopClient.service.CreateLaptop(ctx, req)
if err != nil {
st, ok := status.FromError(err)
if ok && st.Code() == codes.AlreadyExists {
// not a big deal
log.Print("laptop already exists")
} else {
log.Fatal("cannot create laptop: ", err)
}
return
}
log.Printf("created laptop with id: %s", res.Id)
}
// SearchLaptop calls search laptop RPC
func (laptopClient *LaptopClient) SearchLaptop(filter *pb.Filter) {
log.Print("search filter: ", filter)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
req := &pb.SearchLaptopRequest{Filter: filter}
stream, err := laptopClient.service.SearchLaptop(ctx, req)
if err != nil {
log.Fatal("cannot search laptop: ", err)
}
for {
res, err := stream.Recv()
if err == io.EOF {
return
}
if err != nil {
log.Fatal("cannot receive response: ", err)
}
laptop := res.GetLaptop()
log.Print("- found: ", laptop.GetId())
log.Print(" + brand: ", laptop.GetBrand())
log.Print(" + name: ", laptop.GetName())
log.Print(" + cpu cores: ", laptop.GetCpu().GetNumberCores())
log.Print(" + cpu min ghz: ", laptop.GetCpu().GetMinGhz())
log.Print(" + ram: ", laptop.GetRam())
log.Print(" + price: ", laptop.GetPriceUsd())
}
}
// UploadImage calls upload image RPC
func (laptopClient *LaptopClient) UploadImage(laptopID string, imagePath string) {
file, err := os.Open(imagePath)
if err != nil {
log.Fatal("cannot open image file: ", err)
}
defer file.Close()
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
stream, err := laptopClient.service.UploadImage(ctx)
if err != nil {
log.Fatal("cannot upload image: ", err)
}
req := &pb.UploadImageRequest{
Data: &pb.UploadImageRequest_Info{
Info: &pb.ImageInfo{
LaptopId: laptopID,
ImageType: filepath.Ext(imagePath),
},
},
}
err = stream.Send(req)
if err != nil {
log.Fatal("cannot send image info to server: ", err, stream.RecvMsg(nil))
}
reader := bufio.NewReader(file)
buffer := make([]byte, 1024)
for {
n, err := reader.Read(buffer)
if err == io.EOF {
break
}
if err != nil {
log.Fatal("cannot read chunk to buffer: ", err)
}
req := &pb.UploadImageRequest{
Data: &pb.UploadImageRequest_ChunkData{
ChunkData: buffer[:n],
},
}
err = stream.Send(req)
if err != nil {
log.Fatal("cannot send chunk to server: ", err, stream.RecvMsg(nil))
}
}
res, err := stream.CloseAndRecv()
if err != nil {
log.Fatal("cannot receive response: ", err)
}
log.Printf("image uploaded with id: %s, size: %d", res.GetId(), res.GetSize())
}
// RateLaptop calls rate laptop RPC
func (laptopClient *LaptopClient) RateLaptop(laptopIDs []string, scores []float64) error {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
stream, err := laptopClient.service.RateLaptop(ctx)
if err != nil {
return fmt.Errorf("cannot rate laptop: %v", err)
}
waitResponse := make(chan error)
// go routine to receive responses
go func() {
for {
res, err := stream.Recv()
if err == io.EOF {
log.Print("no more responses")
waitResponse <- nil
return
}
if err != nil {
waitResponse <- fmt.Errorf("cannot receive stream response: %v", err)
return
}
log.Print("received response: ", res)
}
}()
// send requests
for i, laptopID := range laptopIDs {
req := &pb.RateLaptopRequest{
LaptopId: laptopID,
Score: scores[i],
}
err := stream.Send(req)
if err != nil {
return fmt.Errorf("cannot send stream request: %v - %v", err, stream.RecvMsg(nil))
}
log.Print("sent request: ", req)
}
err = stream.CloseSend()
if err != nil {
return fmt.Errorf("cannot close send: %v", err)
}
err = <-waitResponse
return err
}
================================================
FILE: cmd/client/main.go
================================================
package main
import (
"crypto/tls"
"crypto/x509"
"flag"
"fmt"
"io/ioutil"
"log"
"strings"
"time"
"gitlab.com/techschool/pcbook/client"
"gitlab.com/techschool/pcbook/pb"
"gitlab.com/techschool/pcbook/sample"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
func testCreateLaptop(laptopClient *client.LaptopClient) {
laptopClient.CreateLaptop(sample.NewLaptop())
}
func testSearchLaptop(laptopClient *client.LaptopClient) {
for i := 0; i < 10; i++ {
laptopClient.CreateLaptop(sample.NewLaptop())
}
filter := &pb.Filter{
MaxPriceUsd: 3000,
MinCpuCores: 4,
MinCpuGhz: 2.5,
MinRam: &pb.Memory{Value: 8, Unit: pb.Memory_GIGABYTE},
}
laptopClient.SearchLaptop(filter)
}
func testUploadImage(laptopClient *client.LaptopClient) {
laptop := sample.NewLaptop()
laptopClient.CreateLaptop(laptop)
laptopClient.UploadImage(laptop.GetId(), "tmp/laptop.jpg")
}
func testRateLaptop(laptopClient *client.LaptopClient) {
n := 3
laptopIDs := make([]string, n)
for i := 0; i < n; i++ {
laptop := sample.NewLaptop()
laptopIDs[i] = laptop.GetId()
laptopClient.CreateLaptop(laptop)
}
scores := make([]float64, n)
for {
fmt.Print("rate laptop (y/n)? ")
var answer string
fmt.Scan(&answer)
if strings.ToLower(answer) != "y" {
break
}
for i := 0; i < n; i++ {
scores[i] = sample.RandomLaptopScore()
}
err := laptopClient.RateLaptop(laptopIDs, scores)
if err != nil {
log.Fatal(err)
}
}
}
const (
username = "admin1"
password = "secret"
refreshDuration = 30 * time.Second
)
func authMethods() map[string]bool {
const laptopServicePath = "/techschool.pcbook.LaptopService/"
return map[string]bool{
laptopServicePath + "CreateLaptop": true,
laptopServicePath + "UploadImage": true,
laptopServicePath + "RateLaptop": true,
}
}
func loadTLSCredentials() (credentials.TransportCredentials, error) {
// Load certificate of the CA who signed server's certificate
pemServerCA, err := ioutil.ReadFile("cert/ca-cert.pem")
if err != nil {
return nil, err
}
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(pemServerCA) {
return nil, fmt.Errorf("failed to add server CA's certificate")
}
// Load client's certificate and private key
clientCert, err := tls.LoadX509KeyPair("cert/client-cert.pem", "cert/client-key.pem")
if err != nil {
return nil, err
}
// Create the credentials and return it
config := &tls.Config{
Certificates: []tls.Certificate{clientCert},
RootCAs: certPool,
}
return credentials.NewTLS(config), nil
}
func main() {
serverAddress := flag.String("address", "", "the server address")
enableTLS := flag.Bool("tls", false, "enable SSL/TLS")
flag.Parse()
log.Printf("dial server %s, TLS = %t", *serverAddress, *enableTLS)
transportOption := grpc.WithInsecure()
if *enableTLS {
tlsCredentials, err := loadTLSCredentials()
if err != nil {
log.Fatal("cannot load TLS credentials: ", err)
}
transportOption = grpc.WithTransportCredentials(tlsCredentials)
}
cc1, err := grpc.Dial(*serverAddress, transportOption)
if err != nil {
log.Fatal("cannot dial server: ", err)
}
authClient := client.NewAuthClient(cc1, username, password)
interceptor, err := client.NewAuthInterceptor(authClient, authMethods(), refreshDuration)
if err != nil {
log.Fatal("cannot create auth interceptor: ", err)
}
cc2, err := grpc.Dial(
*serverAddress,
transportOption,
grpc.WithUnaryInterceptor(interceptor.Unary()),
grpc.WithStreamInterceptor(interceptor.Stream()),
)
if err != nil {
log.Fatal("cannot dial server: ", err)
}
laptopClient := client.NewLaptopClient(cc2)
testRateLaptop(laptopClient)
}
================================================
FILE: cmd/server/main.go
================================================
package main
import (
"context"
"crypto/tls"
"crypto/x509"
"flag"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"time"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"gitlab.com/techschool/pcbook/pb"
"gitlab.com/techschool/pcbook/service"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/reflection"
)
func seedUsers(userStore service.UserStore) error {
err := createUser(userStore, "admin1", "secret", "admin")
if err != nil {
return err
}
return createUser(userStore, "user1", "secret", "user")
}
func createUser(userStore service.UserStore, username, password, role string) error {
user, err := service.NewUser(username, password, role)
if err != nil {
return err
}
return userStore.Save(user)
}
const (
secretKey = "secret"
tokenDuration = 15 * time.Minute
)
const (
serverCertFile = "cert/server-cert.pem"
serverKeyFile = "cert/server-key.pem"
clientCACertFile = "cert/ca-cert.pem"
)
func accessibleRoles() map[string][]string {
const laptopServicePath = "/techschool.pcbook.LaptopService/"
return map[string][]string{
laptopServicePath + "CreateLaptop": {"admin"},
laptopServicePath + "UploadImage": {"admin"},
laptopServicePath + "RateLaptop": {"admin", "user"},
}
}
func loadTLSCredentials() (credentials.TransportCredentials, error) {
// Load certificate of the CA who signed client's certificate
pemClientCA, err := ioutil.ReadFile(clientCACertFile)
if err != nil {
return nil, err
}
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(pemClientCA) {
return nil, fmt.Errorf("failed to add client CA's certificate")
}
// Load server's certificate and private key
serverCert, err := tls.LoadX509KeyPair(serverCertFile, serverKeyFile)
if err != nil {
return nil, err
}
// Create the credentials and return it
config := &tls.Config{
Certificates: []tls.Certificate{serverCert},
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: certPool,
}
return credentials.NewTLS(config), nil
}
func runGRPCServer(
authServer pb.AuthServiceServer,
laptopServer pb.LaptopServiceServer,
jwtManager *service.JWTManager,
enableTLS bool,
listener net.Listener,
) error {
interceptor := service.NewAuthInterceptor(jwtManager, accessibleRoles())
serverOptions := []grpc.ServerOption{
grpc.UnaryInterceptor(interceptor.Unary()),
grpc.StreamInterceptor(interceptor.Stream()),
}
if enableTLS {
tlsCredentials, err := loadTLSCredentials()
if err != nil {
return fmt.Errorf("cannot load TLS credentials: %w", err)
}
serverOptions = append(serverOptions, grpc.Creds(tlsCredentials))
}
grpcServer := grpc.NewServer(serverOptions...)
pb.RegisterAuthServiceServer(grpcServer, authServer)
pb.RegisterLaptopServiceServer(grpcServer, laptopServer)
reflection.Register(grpcServer)
log.Printf("Start GRPC server at %s, TLS = %t", listener.Addr().String(), enableTLS)
return grpcServer.Serve(listener)
}
func runRESTServer(
authServer pb.AuthServiceServer,
laptopServer pb.LaptopServiceServer,
jwtManager *service.JWTManager,
enableTLS bool,
listener net.Listener,
grpcEndpoint string,
) error {
mux := runtime.NewServeMux()
dialOptions := []grpc.DialOption{grpc.WithInsecure()}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// in-process handler
// err := pb.RegisterAuthServiceHandlerServer(ctx, mux, authServer)
err := pb.RegisterAuthServiceHandlerFromEndpoint(ctx, mux, grpcEndpoint, dialOptions)
if err != nil {
return err
}
// in-process handler
// err = pb.RegisterLaptopServiceHandlerServer(ctx, mux, laptopServer)
err = pb.RegisterLaptopServiceHandlerFromEndpoint(ctx, mux, grpcEndpoint, dialOptions)
if err != nil {
return err
}
log.Printf("Start REST server at %s, TLS = %t", listener.Addr().String(), enableTLS)
if enableTLS {
return http.ServeTLS(listener, mux, serverCertFile, serverKeyFile)
}
return http.Serve(listener, mux)
}
func main() {
port := flag.Int("port", 0, "the server port")
enableTLS := flag.Bool("tls", false, "enable SSL/TLS")
serverType := flag.String("type", "grpc", "type of server (grpc/rest)")
endPoint := flag.String("endpoint", "", "gRPC endpoint")
flag.Parse()
userStore := service.NewInMemoryUserStore()
err := seedUsers(userStore)
if err != nil {
log.Fatal("cannot seed users: ", err)
}
jwtManager := service.NewJWTManager(secretKey, tokenDuration)
authServer := service.NewAuthServer(userStore, jwtManager)
laptopStore := service.NewInMemoryLaptopStore()
imageStore := service.NewDiskImageStore("img")
ratingStore := service.NewInMemoryRatingStore()
laptopServer := service.NewLaptopServer(laptopStore, imageStore, ratingStore)
address := fmt.Sprintf("0.0.0.0:%d", *port)
listener, err := net.Listen("tcp", address)
if err != nil {
log.Fatal("cannot start server: ", err)
}
if *serverType == "grpc" {
err = runGRPCServer(authServer, laptopServer, jwtManager, *enableTLS, listener)
} else {
err = runRESTServer(authServer, laptopServer, jwtManager, *enableTLS, listener, *endPoint)
}
if err != nil {
log.Fatal("cannot start server: ", err)
}
}
================================================
FILE: go.mod
================================================
module gitlab.com/techschool/pcbook
go 1.15
require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/golang/protobuf v1.4.3
github.com/google/uuid v1.2.0
github.com/grpc-ecosystem/grpc-gateway/v2 v2.1.0
github.com/jinzhu/copier v0.2.3
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
google.golang.org/genproto v0.0.0-20210202153253-cf70463f6119
google.golang.org/grpc v1.35.0
google.golang.org/protobuf v1.25.0
)
================================================
FILE: go.sum
================================================
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.1.0 h1:EhTvIsn53GrBLl45YVHk25cUHQHwlJfq2y8b7W5IpVY=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.1.0/go.mod h1:ly5QWKtiqC7tGfzgXYtpoZYmEWx5Z82/b18ASEL+yGc=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jinzhu/copier v0.2.3 h1:Oe09ju+9qft7TffZ7l/04AB2f8u1+V4ZMxmp/nnqeOs=
github.com/jinzhu/copier v0.2.3/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24 h1:R8bzl0244nw47n1xKs1MUMAaTNgjavKcN/aX2Ss3+Fo=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210106152847-07624b53cd92 h1:jOTk2Z6KYaWoptUFqZ167cS8peoUPjFEXrsqfVkkCGc=
google.golang.org/genproto v0.0.0-20210106152847-07624b53cd92/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210202153253-cf70463f6119 h1:m9+RjTMas6brUP8DBxSAa/WIPFy7FIhKpvk+9Ppce8E=
google.golang.org/genproto v0.0.0-20210202153253-cf70463f6119/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.34.0 h1:raiipEjMOIC/TO2AvyTxP25XFdLxNIBwzDh3FM3XztI=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0 h1:TwIQcH3es+MojMVojxxfQ3l3OF2KzlRxML2xZq0kRo8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
================================================
FILE: img/.gitkeep
================================================
================================================
FILE: nginx.conf
================================================
worker_processes 1;
error_log /usr/local/var/log/nginx/error.log;
events {
worker_connections 10;
}
http {
access_log /usr/local/var/log/nginx/access.log;
upstream auth_services {
server 0.0.0.0:50051;
server 0.0.0.0:50052;
}
upstream laptop_services {
server 0.0.0.0:50051;
server 0.0.0.0:50052;
}
server {
listen 8080 ssl http2;
# Mutual TLS between gRPC client and nginx
ssl_certificate cert/server-cert.pem;
ssl_certificate_key cert/server-key.pem;
ssl_client_certificate cert/ca-cert.pem;
ssl_verify_client on;
location /techschool.pcbook.AuthService {
grpc_pass grpcs://auth_services;
# Mutual TLS between nginx and gRPC server
grpc_ssl_certificate cert/server-cert.pem;
grpc_ssl_certificate_key cert/server-key.pem;
}
location /techschool.pcbook.LaptopService {
grpc_pass grpcs://laptop_services;
# Mutual TLS between nginx and gRPC server
grpc_ssl_certificate cert/server-cert.pem;
grpc_ssl_certificate_key cert/server-key.pem;
}
}
}
================================================
FILE: pb/auth_service.pb.go
================================================
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0
// protoc v3.14.0
// source: auth_service.proto
package pb
import (
proto "github.com/golang/protobuf/proto"
_ "google.golang.org/genproto/googleapis/api/annotations"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type LoginRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
}
func (x *LoginRequest) Reset() {
*x = LoginRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_auth_service_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *LoginRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LoginRequest) ProtoMessage() {}
func (x *LoginRequest) ProtoReflect() protoreflect.Message {
mi := &file_auth_service_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LoginRequest.ProtoReflect.Descriptor instead.
func (*LoginRequest) Descriptor() ([]byte, []int) {
return file_auth_service_proto_rawDescGZIP(), []int{0}
}
func (x *LoginRequest) GetUsername() string {
if x != nil {
return x.Username
}
return ""
}
func (x *LoginRequest) GetPassword() string {
if x != nil {
return x.Password
}
return ""
}
type LoginResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
}
func (x *LoginResponse) Reset() {
*x = LoginResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_auth_service_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *LoginResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*LoginResponse) ProtoMessage() {}
func (x *LoginResponse) ProtoReflect() protoreflect.Message {
mi := &file_auth_service_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use LoginResponse.ProtoReflect.Descriptor instead.
func (*LoginResponse) Descriptor() ([]byte, []int) {
return file_auth_service_proto_rawDescGZIP(), []int{1}
}
func (x *LoginResponse) GetAccessToken() string {
if x != nil {
return x.AccessToken
}
return ""
}
var File_auth_service_proto protoreflect.FileDescriptor
var file_auth_service_proto_rawDesc = []byte{
0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c,
0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x46, 0x0a, 0x0c, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x32, 0x0a,
0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21,
0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65,
0x6e, 0x32, 0x74, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x12, 0x65, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x1f, 0x2e, 0x74, 0x65, 0x63, 0x68,
0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4c, 0x6f,
0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x74, 0x65, 0x63,
0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4c,
0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3,
0xe4, 0x93, 0x02, 0x13, 0x22, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x6c,
0x6f, 0x67, 0x69, 0x6e, 0x3a, 0x01, 0x2a, 0x42, 0x29, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x67,
0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c,
0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x70, 0x62, 0x50, 0x01, 0x5a, 0x04, 0x2e, 0x3b,
0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_auth_service_proto_rawDescOnce sync.Once
file_auth_service_proto_rawDescData = file_auth_service_proto_rawDesc
)
func file_auth_service_proto_rawDescGZIP() []byte {
file_auth_service_proto_rawDescOnce.Do(func() {
file_auth_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_auth_service_proto_rawDescData)
})
return file_auth_service_proto_rawDescData
}
var file_auth_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_auth_service_proto_goTypes = []interface{}{
(*LoginRequest)(nil), // 0: techschool.pcbook.LoginRequest
(*LoginResponse)(nil), // 1: techschool.pcbook.LoginResponse
}
var file_auth_service_proto_depIdxs = []int32{
0, // 0: techschool.pcbook.AuthService.Login:input_type -> techschool.pcbook.LoginRequest
1, // 1: techschool.pcbook.AuthService.Login:output_type -> techschool.pcbook.LoginResponse
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_auth_service_proto_init() }
func file_auth_service_proto_init() {
if File_auth_service_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_auth_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*LoginRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_auth_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*LoginResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_auth_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_auth_service_proto_goTypes,
DependencyIndexes: file_auth_service_proto_depIdxs,
MessageInfos: file_auth_service_proto_msgTypes,
}.Build()
File_auth_service_proto = out.File
file_auth_service_proto_rawDesc = nil
file_auth_service_proto_goTypes = nil
file_auth_service_proto_depIdxs = nil
}
================================================
FILE: pb/auth_service.pb.gw.go
================================================
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
// source: auth_service.proto
/*
Package pb is a reverse proxy.
It translates gRPC into RESTful JSON APIs.
*/
package pb
import (
"context"
"io"
"net/http"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
)
// Suppress "imported and not used" errors
var _ codes.Code
var _ io.Reader
var _ status.Status
var _ = runtime.String
var _ = utilities.NewDoubleArray
var _ = metadata.Join
func request_AuthService_Login_0(ctx context.Context, marshaler runtime.Marshaler, client AuthServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq LoginRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.Login(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_AuthService_Login_0(ctx context.Context, marshaler runtime.Marshaler, server AuthServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq LoginRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.Login(ctx, &protoReq)
return msg, metadata, err
}
// RegisterAuthServiceHandlerServer registers the http handlers for service AuthService to "mux".
// UnaryRPC :call AuthServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterAuthServiceHandlerFromEndpoint instead.
func RegisterAuthServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AuthServiceServer) error {
mux.Handle("POST", pattern_AuthService_Login_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/techschool.pcbook.AuthService/Login")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_AuthService_Login_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AuthService_Login_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
// RegisterAuthServiceHandlerFromEndpoint is same as RegisterAuthServiceHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterAuthServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
conn, err := grpc.Dial(endpoint, opts...)
if err != nil {
return err
}
defer func() {
if err != nil {
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
return
}
go func() {
<-ctx.Done()
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
}()
}()
return RegisterAuthServiceHandler(ctx, mux, conn)
}
// RegisterAuthServiceHandler registers the http handlers for service AuthService to "mux".
// The handlers forward requests to the grpc endpoint over "conn".
func RegisterAuthServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
return RegisterAuthServiceHandlerClient(ctx, mux, NewAuthServiceClient(conn))
}
// RegisterAuthServiceHandlerClient registers the http handlers for service AuthService
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "AuthServiceClient".
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "AuthServiceClient"
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
// "AuthServiceClient" to call the correct interceptors.
func RegisterAuthServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AuthServiceClient) error {
mux.Handle("POST", pattern_AuthService_Login_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/techschool.pcbook.AuthService/Login")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_AuthService_Login_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_AuthService_Login_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
var (
pattern_AuthService_Login_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "auth", "login"}, ""))
)
var (
forward_AuthService_Login_0 = runtime.ForwardResponseMessage
)
================================================
FILE: pb/auth_service_grpc.pb.go
================================================
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package pb
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// AuthServiceClient is the client API for AuthService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type AuthServiceClient interface {
Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
}
type authServiceClient struct {
cc grpc.ClientConnInterface
}
func NewAuthServiceClient(cc grpc.ClientConnInterface) AuthServiceClient {
return &authServiceClient{cc}
}
func (c *authServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) {
out := new(LoginResponse)
err := c.cc.Invoke(ctx, "/techschool.pcbook.AuthService/Login", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// AuthServiceServer is the server API for AuthService service.
// All implementations must embed UnimplementedAuthServiceServer
// for forward compatibility
type AuthServiceServer interface {
Login(context.Context, *LoginRequest) (*LoginResponse, error)
mustEmbedUnimplementedAuthServiceServer()
}
// UnimplementedAuthServiceServer must be embedded to have forward compatible implementations.
type UnimplementedAuthServiceServer struct {
}
func (UnimplementedAuthServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
}
func (UnimplementedAuthServiceServer) mustEmbedUnimplementedAuthServiceServer() {}
// UnsafeAuthServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to AuthServiceServer will
// result in compilation errors.
type UnsafeAuthServiceServer interface {
mustEmbedUnimplementedAuthServiceServer()
}
func RegisterAuthServiceServer(s grpc.ServiceRegistrar, srv AuthServiceServer) {
s.RegisterService(&AuthService_ServiceDesc, srv)
}
func _AuthService_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LoginRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).Login(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/techschool.pcbook.AuthService/Login",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).Login(ctx, req.(*LoginRequest))
}
return interceptor(ctx, in, info, handler)
}
// AuthService_ServiceDesc is the grpc.ServiceDesc for AuthService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var AuthService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "techschool.pcbook.AuthService",
HandlerType: (*AuthServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Login",
Handler: _AuthService_Login_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "auth_service.proto",
}
================================================
FILE: pb/filter_message.pb.go
================================================
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0
// protoc v3.14.0
// source: filter_message.proto
package pb
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type Filter struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
MaxPriceUsd float64 `protobuf:"fixed64,1,opt,name=max_price_usd,json=maxPriceUsd,proto3" json:"max_price_usd,omitempty"`
MinCpuCores uint32 `protobuf:"varint,2,opt,name=min_cpu_cores,json=minCpuCores,proto3" json:"min_cpu_cores,omitempty"`
MinCpuGhz float64 `protobuf:"fixed64,3,opt,name=min_cpu_ghz,json=minCpuGhz,proto3" json:"min_cpu_ghz,omitempty"`
MinRam *Memory `protobuf:"bytes,4,opt,name=min_ram,json=minRam,proto3" json:"min_ram,omitempty"`
}
func (x *Filter) Reset() {
*x = Filter{}
if protoimpl.UnsafeEnabled {
mi := &file_filter_message_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Filter) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Filter) ProtoMessage() {}
func (x *Filter) ProtoReflect() protoreflect.Message {
mi := &file_filter_message_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Filter.ProtoReflect.Descriptor instead.
func (*Filter) Descriptor() ([]byte, []int) {
return file_filter_message_proto_rawDescGZIP(), []int{0}
}
func (x *Filter) GetMaxPriceUsd() float64 {
if x != nil {
return x.MaxPriceUsd
}
return 0
}
func (x *Filter) GetMinCpuCores() uint32 {
if x != nil {
return x.MinCpuCores
}
return 0
}
func (x *Filter) GetMinCpuGhz() float64 {
if x != nil {
return x.MinCpuGhz
}
return 0
}
func (x *Filter) GetMinRam() *Memory {
if x != nil {
return x.MinRam
}
return nil
}
var File_filter_message_proto protoreflect.FileDescriptor
var file_filter_message_proto_rawDesc = []byte{
0x0a, 0x14, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f,
0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x1a, 0x14, 0x6d, 0x65, 0x6d, 0x6f, 0x72,
0x79, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
0xa4, 0x01, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61,
0x78, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x01, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x50, 0x72, 0x69, 0x63, 0x65, 0x55, 0x73, 0x64, 0x12, 0x22,
0x0a, 0x0d, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x6d, 0x69, 0x6e, 0x43, 0x70, 0x75, 0x43, 0x6f, 0x72,
0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x67, 0x68,
0x7a, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x6d, 0x69, 0x6e, 0x43, 0x70, 0x75, 0x47,
0x68, 0x7a, 0x12, 0x32, 0x0a, 0x07, 0x6d, 0x69, 0x6e, 0x5f, 0x72, 0x61, 0x6d, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c,
0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x52, 0x06,
0x6d, 0x69, 0x6e, 0x52, 0x61, 0x6d, 0x42, 0x29, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x69,
0x74, 0x6c, 0x61, 0x62, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e,
0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x70, 0x62, 0x50, 0x01, 0x5a, 0x04, 0x2e, 0x3b, 0x70,
0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_filter_message_proto_rawDescOnce sync.Once
file_filter_message_proto_rawDescData = file_filter_message_proto_rawDesc
)
func file_filter_message_proto_rawDescGZIP() []byte {
file_filter_message_proto_rawDescOnce.Do(func() {
file_filter_message_proto_rawDescData = protoimpl.X.CompressGZIP(file_filter_message_proto_rawDescData)
})
return file_filter_message_proto_rawDescData
}
var file_filter_message_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_filter_message_proto_goTypes = []interface{}{
(*Filter)(nil), // 0: techschool.pcbook.Filter
(*Memory)(nil), // 1: techschool.pcbook.Memory
}
var file_filter_message_proto_depIdxs = []int32{
1, // 0: techschool.pcbook.Filter.min_ram:type_name -> techschool.pcbook.Memory
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_filter_message_proto_init() }
func file_filter_message_proto_init() {
if File_filter_message_proto != nil {
return
}
file_memory_message_proto_init()
if !protoimpl.UnsafeEnabled {
file_filter_message_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Filter); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_filter_message_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_filter_message_proto_goTypes,
DependencyIndexes: file_filter_message_proto_depIdxs,
MessageInfos: file_filter_message_proto_msgTypes,
}.Build()
File_filter_message_proto = out.File
file_filter_message_proto_rawDesc = nil
file_filter_message_proto_goTypes = nil
file_filter_message_proto_depIdxs = nil
}
================================================
FILE: pb/keyboard_message.pb.go
================================================
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0
// protoc v3.14.0
// source: keyboard_message.proto
package pb
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type Keyboard_Layout int32
const (
Keyboard_UNKNOWN Keyboard_Layout = 0
Keyboard_QWERTY Keyboard_Layout = 1
Keyboard_QWERTZ Keyboard_Layout = 2
Keyboard_AZERTY Keyboard_Layout = 3
)
// Enum value maps for Keyboard_Layout.
var (
Keyboard_Layout_name = map[int32]string{
0: "UNKNOWN",
1: "QWERTY",
2: "QWERTZ",
3: "AZERTY",
}
Keyboard_Layout_value = map[string]int32{
"UNKNOWN": 0,
"QWERTY": 1,
"QWERTZ": 2,
"AZERTY": 3,
}
)
func (x Keyboard_Layout) Enum() *Keyboard_Layout {
p := new(Keyboard_Layout)
*p = x
return p
}
func (x Keyboard_Layout) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (Keyboard_Layout) Descriptor() protoreflect.EnumDescriptor {
return file_keyboard_message_proto_enumTypes[0].Descriptor()
}
func (Keyboard_Layout) Type() protoreflect.EnumType {
return &file_keyboard_message_proto_enumTypes[0]
}
func (x Keyboard_Layout) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use Keyboard_Layout.Descriptor instead.
func (Keyboard_Layout) EnumDescriptor() ([]byte, []int) {
return file_keyboard_message_proto_rawDescGZIP(), []int{0, 0}
}
type Keyboard struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Layout Keyboard_Layout `protobuf:"varint,1,opt,name=layout,proto3,enum=techschool.pcbook.Keyboard_Layout" json:"layout,omitempty"`
Backlit bool `protobuf:"varint,2,opt,name=backlit,proto3" json:"backlit,omitempty"`
}
func (x *Keyboard) Reset() {
*x = Keyboard{}
if protoimpl.UnsafeEnabled {
mi := &file_keyboard_message_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Keyboard) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Keyboard) ProtoMessage() {}
func (x *Keyboard) ProtoReflect() protoreflect.Message {
mi := &file_keyboard_message_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Keyboard.ProtoReflect.Descriptor instead.
func (*Keyboard) Descriptor() ([]byte, []int) {
return file_keyboard_message_proto_rawDescGZIP(), []int{0}
}
func (x *Keyboard) GetLayout() Keyboard_Layout {
if x != nil {
return x.Layout
}
return Keyboard_UNKNOWN
}
func (x *Keyboard) GetBacklit() bool {
if x != nil {
return x.Backlit
}
return false
}
var File_keyboard_message_proto protoreflect.FileDescriptor
var file_keyboard_message_proto_rawDesc = []byte{
0x0a, 0x16, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63,
0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x22, 0x9b, 0x01, 0x0a, 0x08,
0x4b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x3a, 0x0a, 0x06, 0x6c, 0x61, 0x79, 0x6f,
0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73,
0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4b, 0x65, 0x79,
0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x4c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x52, 0x06, 0x6c, 0x61,
0x79, 0x6f, 0x75, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x6c, 0x69, 0x74, 0x18,
0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x62, 0x61, 0x63, 0x6b, 0x6c, 0x69, 0x74, 0x22, 0x39,
0x0a, 0x06, 0x4c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e,
0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x10,
0x01, 0x12, 0x0a, 0x0a, 0x06, 0x51, 0x57, 0x45, 0x52, 0x54, 0x5a, 0x10, 0x02, 0x12, 0x0a, 0x0a,
0x06, 0x41, 0x5a, 0x45, 0x52, 0x54, 0x59, 0x10, 0x03, 0x42, 0x29, 0x0a, 0x1f, 0x63, 0x6f, 0x6d,
0x2e, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f,
0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x70, 0x62, 0x50, 0x01, 0x5a, 0x04,
0x2e, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_keyboard_message_proto_rawDescOnce sync.Once
file_keyboard_message_proto_rawDescData = file_keyboard_message_proto_rawDesc
)
func file_keyboard_message_proto_rawDescGZIP() []byte {
file_keyboard_message_proto_rawDescOnce.Do(func() {
file_keyboard_message_proto_rawDescData = protoimpl.X.CompressGZIP(file_keyboard_message_proto_rawDescData)
})
return file_keyboard_message_proto_rawDescData
}
var file_keyboard_message_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_keyboard_message_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_keyboard_message_proto_goTypes = []interface{}{
(Keyboard_Layout)(0), // 0: techschool.pcbook.Keyboard.Layout
(*Keyboard)(nil), // 1: techschool.pcbook.Keyboard
}
var file_keyboard_message_proto_depIdxs = []int32{
0, // 0: techschool.pcbook.Keyboard.layout:type_name -> techschool.pcbook.Keyboard.Layout
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_keyboard_message_proto_init() }
func file_keyboard_message_proto_init() {
if File_keyboard_message_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_keyboard_message_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Keyboard); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_keyboard_message_proto_rawDesc,
NumEnums: 1,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_keyboard_message_proto_goTypes,
DependencyIndexes: file_keyboard_message_proto_depIdxs,
EnumInfos: file_keyboard_message_proto_enumTypes,
MessageInfos: file_keyboard_message_proto_msgTypes,
}.Build()
File_keyboard_message_proto = out.File
file_keyboard_message_proto_rawDesc = nil
file_keyboard_message_proto_goTypes = nil
file_keyboard_message_proto_depIdxs = nil
}
================================================
FILE: pb/laptop_message.pb.go
================================================
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0
// protoc v3.14.0
// source: laptop_message.proto
package pb
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type Laptop struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Brand string `protobuf:"bytes,2,opt,name=brand,proto3" json:"brand,omitempty"`
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
Cpu *CPU `protobuf:"bytes,4,opt,name=cpu,proto3" json:"cpu,omitempty"`
Ram *Memory `protobuf:"bytes,5,opt,name=ram,proto3" json:"ram,omitempty"`
Gpus []*GPU `protobuf:"bytes,6,rep,name=gpus,proto3" json:"gpus,omitempty"`
Storages []*Storage `protobuf:"bytes,7,rep,name=storages,proto3" json:"storages,omitempty"`
Screen *Screen `protobuf:"bytes,8,opt,name=screen,proto3" json:"screen,omitempty"`
Keyboard *Keyboard `protobuf:"bytes,9,opt,name=keyboard,proto3" json:"keyboard,omitempty"`
// Types that are assignable to Weight:
// *Laptop_WeightKg
// *Laptop_WeightLb
Weight isLaptop_Weight `protobuf_oneof:"weight"`
PriceUsd float64 `protobuf:"fixed64,12,opt,name=price_usd,json=priceUsd,proto3" json:"price_usd,omitempty"`
ReleaseYear uint32 `protobuf:"varint,13,opt,name=release_year,json=releaseYear,proto3" json:"release_year,omitempty"`
UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,14,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
}
func (x *Laptop) Reset() {
*x = Laptop{}
if protoimpl.UnsafeEnabled {
mi := &file_laptop_message_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Laptop) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Laptop) ProtoMessage() {}
func (x *Laptop) ProtoReflect() protoreflect.Message {
mi := &file_laptop_message_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Laptop.ProtoReflect.Descriptor instead.
func (*Laptop) Descriptor() ([]byte, []int) {
return file_laptop_message_proto_rawDescGZIP(), []int{0}
}
func (x *Laptop) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *Laptop) GetBrand() string {
if x != nil {
return x.Brand
}
return ""
}
func (x *Laptop) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Laptop) GetCpu() *CPU {
if x != nil {
return x.Cpu
}
return nil
}
func (x *Laptop) GetRam() *Memory {
if x != nil {
return x.Ram
}
return nil
}
func (x *Laptop) GetGpus() []*GPU {
if x != nil {
return x.Gpus
}
return nil
}
func (x *Laptop) GetStorages() []*Storage {
if x != nil {
return x.Storages
}
return nil
}
func (x *Laptop) GetScreen() *Screen {
if x != nil {
return x.Screen
}
return nil
}
func (x *Laptop) GetKeyboard() *Keyboard {
if x != nil {
return x.Keyboard
}
return nil
}
func (m *Laptop) GetWeight() isLaptop_Weight {
if m != nil {
return m.Weight
}
return nil
}
func (x *Laptop) GetWeightKg() float64 {
if x, ok := x.GetWeight().(*Laptop_WeightKg); ok {
return x.WeightKg
}
return 0
}
func (x *Laptop) GetWeightLb() float64 {
if x, ok := x.GetWeight().(*Laptop_WeightLb); ok {
return x.WeightLb
}
return 0
}
func (x *Laptop) GetPriceUsd() float64 {
if x != nil {
return x.PriceUsd
}
return 0
}
func (x *Laptop) GetReleaseYear() uint32 {
if x != nil {
return x.ReleaseYear
}
return 0
}
func (x *Laptop) GetUpdatedAt() *timestamppb.Timestamp {
if x != nil {
return x.UpdatedAt
}
return nil
}
type isLaptop_Weight interface {
isLaptop_Weight()
}
type Laptop_WeightKg struct {
WeightKg float64 `protobuf:"fixed64,10,opt,name=weight_kg,json=weightKg,proto3,oneof"`
}
type Laptop_WeightLb struct {
WeightLb float64 `protobuf:"fixed64,11,opt,name=weight_lb,json=weightLb,proto3,oneof"`
}
func (*Laptop_WeightKg) isLaptop_Weight() {}
func (*Laptop_WeightLb) isLaptop_Weight() {}
var File_laptop_message_proto protoreflect.FileDescriptor
var file_laptop_message_proto_rawDesc = []byte{
0x0a, 0x14, 0x6c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f,
0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x1a, 0x17, 0x70, 0x72, 0x6f, 0x63, 0x65,
0x73, 0x73, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x1a, 0x14, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67,
0x65, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
0x14, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x16, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f,
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74,
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xac,
0x04, 0x0a, 0x06, 0x4c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x72, 0x61,
0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x62, 0x72, 0x61, 0x6e, 0x64, 0x12,
0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x03, 0x63, 0x70, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x16, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63,
0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x43, 0x50, 0x55, 0x52, 0x03, 0x63, 0x70, 0x75, 0x12, 0x2b, 0x0a,
0x03, 0x72, 0x61, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x65, 0x63,
0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4d,
0x65, 0x6d, 0x6f, 0x72, 0x79, 0x52, 0x03, 0x72, 0x61, 0x6d, 0x12, 0x2a, 0x0a, 0x04, 0x67, 0x70,
0x75, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73,
0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x47, 0x50, 0x55,
0x52, 0x04, 0x67, 0x70, 0x75, 0x73, 0x12, 0x36, 0x0a, 0x08, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67,
0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73,
0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x53, 0x74, 0x6f,
0x72, 0x61, 0x67, 0x65, 0x52, 0x08, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x73, 0x12, 0x31,
0x0a, 0x06, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19,
0x2e, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f,
0x6f, 0x6b, 0x2e, 0x53, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x52, 0x06, 0x73, 0x63, 0x72, 0x65, 0x65,
0x6e, 0x12, 0x37, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x18, 0x09, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c,
0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64,
0x52, 0x08, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x0a, 0x09, 0x77, 0x65,
0x69, 0x67, 0x68, 0x74, 0x5f, 0x6b, 0x67, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52,
0x08, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4b, 0x67, 0x12, 0x1d, 0x0a, 0x09, 0x77, 0x65, 0x69,
0x67, 0x68, 0x74, 0x5f, 0x6c, 0x62, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x08,
0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x62, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x69, 0x63,
0x65, 0x5f, 0x75, 0x73, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x70, 0x72, 0x69,
0x63, 0x65, 0x55, 0x73, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65,
0x5f, 0x79, 0x65, 0x61, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x72, 0x65, 0x6c,
0x65, 0x61, 0x73, 0x65, 0x59, 0x65, 0x61, 0x72, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61,
0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54,
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
0x64, 0x41, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x42, 0x29, 0x0a,
0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x74, 0x65, 0x63, 0x68,
0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x70, 0x62,
0x50, 0x01, 0x5a, 0x04, 0x2e, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_laptop_message_proto_rawDescOnce sync.Once
file_laptop_message_proto_rawDescData = file_laptop_message_proto_rawDesc
)
func file_laptop_message_proto_rawDescGZIP() []byte {
file_laptop_message_proto_rawDescOnce.Do(func() {
file_laptop_message_proto_rawDescData = protoimpl.X.CompressGZIP(file_laptop_message_proto_rawDescData)
})
return file_laptop_message_proto_rawDescData
}
var file_laptop_message_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_laptop_message_proto_goTypes = []interface{}{
(*Laptop)(nil), // 0: techschool.pcbook.Laptop
(*CPU)(nil), // 1: techschool.pcbook.CPU
(*Memory)(nil), // 2: techschool.pcbook.Memory
(*GPU)(nil), // 3: techschool.pcbook.GPU
(*Storage)(nil), // 4: techschool.pcbook.Storage
(*Screen)(nil), // 5: techschool.pcbook.Screen
(*Keyboard)(nil), // 6: techschool.pcbook.Keyboard
(*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp
}
var file_laptop_message_proto_depIdxs = []int32{
1, // 0: techschool.pcbook.Laptop.cpu:type_name -> techschool.pcbook.CPU
2, // 1: techschool.pcbook.Laptop.ram:type_name -> techschool.pcbook.Memory
3, // 2: techschool.pcbook.Laptop.gpus:type_name -> techschool.pcbook.GPU
4, // 3: techschool.pcbook.Laptop.storages:type_name -> techschool.pcbook.Storage
5, // 4: techschool.pcbook.Laptop.screen:type_name -> techschool.pcbook.Screen
6, // 5: techschool.pcbook.Laptop.keyboard:type_name -> techschool.pcbook.Keyboard
7, // 6: techschool.pcbook.Laptop.updated_at:type_name -> google.protobuf.Timestamp
7, // [7:7] is the sub-list for method output_type
7, // [7:7] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
}
func init() { file_laptop_message_proto_init() }
func file_laptop_message_proto_init() {
if File_laptop_message_proto != nil {
return
}
file_processor_message_proto_init()
file_memory_message_proto_init()
file_storage_message_proto_init()
file_screen_message_proto_init()
file_keyboard_message_proto_init()
if !protoimpl.UnsafeEnabled {
file_laptop_message_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Laptop); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_laptop_message_proto_msgTypes[0].OneofWrappers = []interface{}{
(*Laptop_WeightKg)(nil),
(*Laptop_WeightLb)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_laptop_message_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_laptop_message_proto_goTypes,
DependencyIndexes: file_laptop_message_proto_depIdxs,
MessageInfos: file_laptop_message_proto_msgTypes,
}.Build()
File_laptop_message_proto = out.File
file_laptop_message_proto_rawDesc = nil
file_laptop_message_proto_goTypes = nil
file_laptop_message_proto_depIdxs = nil
}
================================================
FILE: pb/laptop_service.pb.go
================================================
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0
// protoc v3.14.0
// source: laptop_service.proto
package pb
import (
proto "github.com/golang/protobuf/proto"
_ "google.golang.org/genproto/googleapis/api/annotations"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type CreateLaptopRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Laptop *Laptop `protobuf:"bytes,1,opt,name=laptop,proto3" json:"laptop,omitempty"`
}
func (x *CreateLaptopRequest) Reset() {
*x = CreateLaptopRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_laptop_service_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CreateLaptopRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateLaptopRequest) ProtoMessage() {}
func (x *CreateLaptopRequest) ProtoReflect() protoreflect.Message {
mi := &file_laptop_service_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateLaptopRequest.ProtoReflect.Descriptor instead.
func (*CreateLaptopRequest) Descriptor() ([]byte, []int) {
return file_laptop_service_proto_rawDescGZIP(), []int{0}
}
func (x *CreateLaptopRequest) GetLaptop() *Laptop {
if x != nil {
return x.Laptop
}
return nil
}
type CreateLaptopResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
}
func (x *CreateLaptopResponse) Reset() {
*x = CreateLaptopResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_laptop_service_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CreateLaptopResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CreateLaptopResponse) ProtoMessage() {}
func (x *CreateLaptopResponse) ProtoReflect() protoreflect.Message {
mi := &file_laptop_service_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CreateLaptopResponse.ProtoReflect.Descriptor instead.
func (*CreateLaptopResponse) Descriptor() ([]byte, []int) {
return file_laptop_service_proto_rawDescGZIP(), []int{1}
}
func (x *CreateLaptopResponse) GetId() string {
if x != nil {
return x.Id
}
return ""
}
type SearchLaptopRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Filter *Filter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"`
}
func (x *SearchLaptopRequest) Reset() {
*x = SearchLaptopRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_laptop_service_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SearchLaptopRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SearchLaptopRequest) ProtoMessage() {}
func (x *SearchLaptopRequest) ProtoReflect() protoreflect.Message {
mi := &file_laptop_service_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SearchLaptopRequest.ProtoReflect.Descriptor instead.
func (*SearchLaptopRequest) Descriptor() ([]byte, []int) {
return file_laptop_service_proto_rawDescGZIP(), []int{2}
}
func (x *SearchLaptopRequest) GetFilter() *Filter {
if x != nil {
return x.Filter
}
return nil
}
type SearchLaptopResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Laptop *Laptop `protobuf:"bytes,1,opt,name=laptop,proto3" json:"laptop,omitempty"`
}
func (x *SearchLaptopResponse) Reset() {
*x = SearchLaptopResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_laptop_service_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SearchLaptopResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SearchLaptopResponse) ProtoMessage() {}
func (x *SearchLaptopResponse) ProtoReflect() protoreflect.Message {
mi := &file_laptop_service_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SearchLaptopResponse.ProtoReflect.Descriptor instead.
func (*SearchLaptopResponse) Descriptor() ([]byte, []int) {
return file_laptop_service_proto_rawDescGZIP(), []int{3}
}
func (x *SearchLaptopResponse) GetLaptop() *Laptop {
if x != nil {
return x.Laptop
}
return nil
}
type UploadImageRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Types that are assignable to Data:
// *UploadImageRequest_Info
// *UploadImageRequest_ChunkData
Data isUploadImageRequest_Data `protobuf_oneof:"data"`
}
func (x *UploadImageRequest) Reset() {
*x = UploadImageRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_laptop_service_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UploadImageRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UploadImageRequest) ProtoMessage() {}
func (x *UploadImageRequest) ProtoReflect() protoreflect.Message {
mi := &file_laptop_service_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UploadImageRequest.ProtoReflect.Descriptor instead.
func (*UploadImageRequest) Descriptor() ([]byte, []int) {
return file_laptop_service_proto_rawDescGZIP(), []int{4}
}
func (m *UploadImageRequest) GetData() isUploadImageRequest_Data {
if m != nil {
return m.Data
}
return nil
}
func (x *UploadImageRequest) GetInfo() *ImageInfo {
if x, ok := x.GetData().(*UploadImageRequest_Info); ok {
return x.Info
}
return nil
}
func (x *UploadImageRequest) GetChunkData() []byte {
if x, ok := x.GetData().(*UploadImageRequest_ChunkData); ok {
return x.ChunkData
}
return nil
}
type isUploadImageRequest_Data interface {
isUploadImageRequest_Data()
}
type UploadImageRequest_Info struct {
Info *ImageInfo `protobuf:"bytes,1,opt,name=info,proto3,oneof"`
}
type UploadImageRequest_ChunkData struct {
ChunkData []byte `protobuf:"bytes,2,opt,name=chunk_data,json=chunkData,proto3,oneof"`
}
func (*UploadImageRequest_Info) isUploadImageRequest_Data() {}
func (*UploadImageRequest_ChunkData) isUploadImageRequest_Data() {}
type ImageInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
LaptopId string `protobuf:"bytes,1,opt,name=laptop_id,json=laptopId,proto3" json:"laptop_id,omitempty"`
ImageType string `protobuf:"bytes,2,opt,name=image_type,json=imageType,proto3" json:"image_type,omitempty"`
}
func (x *ImageInfo) Reset() {
*x = ImageInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_laptop_service_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ImageInfo) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ImageInfo) ProtoMessage() {}
func (x *ImageInfo) ProtoReflect() protoreflect.Message {
mi := &file_laptop_service_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ImageInfo.ProtoReflect.Descriptor instead.
func (*ImageInfo) Descriptor() ([]byte, []int) {
return file_laptop_service_proto_rawDescGZIP(), []int{5}
}
func (x *ImageInfo) GetLaptopId() string {
if x != nil {
return x.LaptopId
}
return ""
}
func (x *ImageInfo) GetImageType() string {
if x != nil {
return x.ImageType
}
return ""
}
type UploadImageResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Size uint32 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"`
}
func (x *UploadImageResponse) Reset() {
*x = UploadImageResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_laptop_service_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *UploadImageResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UploadImageResponse) ProtoMessage() {}
func (x *UploadImageResponse) ProtoReflect() protoreflect.Message {
mi := &file_laptop_service_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UploadImageResponse.ProtoReflect.Descriptor instead.
func (*UploadImageResponse) Descriptor() ([]byte, []int) {
return file_laptop_service_proto_rawDescGZIP(), []int{6}
}
func (x *UploadImageResponse) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *UploadImageResponse) GetSize() uint32 {
if x != nil {
return x.Size
}
return 0
}
type RateLaptopRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
LaptopId string `protobuf:"bytes,1,opt,name=laptop_id,json=laptopId,proto3" json:"laptop_id,omitempty"`
Score float64 `protobuf:"fixed64,2,opt,name=score,proto3" json:"score,omitempty"`
}
func (x *RateLaptopRequest) Reset() {
*x = RateLaptopRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_laptop_service_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RateLaptopRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RateLaptopRequest) ProtoMessage() {}
func (x *RateLaptopRequest) ProtoReflect() protoreflect.Message {
mi := &file_laptop_service_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RateLaptopRequest.ProtoReflect.Descriptor instead.
func (*RateLaptopRequest) Descriptor() ([]byte, []int) {
return file_laptop_service_proto_rawDescGZIP(), []int{7}
}
func (x *RateLaptopRequest) GetLaptopId() string {
if x != nil {
return x.LaptopId
}
return ""
}
func (x *RateLaptopRequest) GetScore() float64 {
if x != nil {
return x.Score
}
return 0
}
type RateLaptopResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
LaptopId string `protobuf:"bytes,1,opt,name=laptop_id,json=laptopId,proto3" json:"laptop_id,omitempty"`
RatedCount uint32 `protobuf:"varint,2,opt,name=rated_count,json=ratedCount,proto3" json:"rated_count,omitempty"`
AverageScore float64 `protobuf:"fixed64,3,opt,name=average_score,json=averageScore,proto3" json:"average_score,omitempty"`
}
func (x *RateLaptopResponse) Reset() {
*x = RateLaptopResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_laptop_service_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RateLaptopResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RateLaptopResponse) ProtoMessage() {}
func (x *RateLaptopResponse) ProtoReflect() protoreflect.Message {
mi := &file_laptop_service_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RateLaptopResponse.ProtoReflect.Descriptor instead.
func (*RateLaptopResponse) Descriptor() ([]byte, []int) {
return file_laptop_service_proto_rawDescGZIP(), []int{8}
}
func (x *RateLaptopResponse) GetLaptopId() string {
if x != nil {
return x.LaptopId
}
return ""
}
func (x *RateLaptopResponse) GetRatedCount() uint32 {
if x != nil {
return x.RatedCount
}
return 0
}
func (x *RateLaptopResponse) GetAverageScore() float64 {
if x != nil {
return x.AverageScore
}
return 0
}
var File_laptop_service_proto protoreflect.FileDescriptor
var file_laptop_service_proto_rawDesc = []byte{
0x0a, 0x14, 0x6c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f,
0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x1a, 0x14, 0x6c, 0x61, 0x70, 0x74, 0x6f,
0x70, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
0x14, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0x48, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x61, 0x70,
0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x06, 0x6c, 0x61,
0x70, 0x74, 0x6f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x65, 0x63,
0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4c,
0x61, 0x70, 0x74, 0x6f, 0x70, 0x52, 0x06, 0x6c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x22, 0x26, 0x0a,
0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x48, 0x0a, 0x13, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c,
0x61, 0x70, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x06,
0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74,
0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b,
0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22,
0x49, 0x0a, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x6c, 0x61, 0x70, 0x74, 0x6f,
0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63,
0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4c, 0x61, 0x70, 0x74,
0x6f, 0x70, 0x52, 0x06, 0x6c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x22, 0x71, 0x0a, 0x12, 0x55, 0x70,
0x6c, 0x6f, 0x61, 0x64, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x32, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
0x2e, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f,
0x6f, 0x6b, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x04,
0x69, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x0a, 0x0a, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x5f, 0x64, 0x61,
0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x09, 0x63, 0x68, 0x75, 0x6e,
0x6b, 0x44, 0x61, 0x74, 0x61, 0x42, 0x06, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x47, 0x0a,
0x09, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x61,
0x70, 0x74, 0x6f, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c,
0x61, 0x70, 0x74, 0x6f, 0x70, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65,
0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6d, 0x61,
0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x39, 0x0a, 0x13, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64,
0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a,
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a,
0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a,
0x65, 0x22, 0x46, 0x0a, 0x11, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x61, 0x70, 0x74, 0x6f, 0x70,
0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x70, 0x74, 0x6f,
0x70, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01,
0x28, 0x01, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x22, 0x77, 0x0a, 0x12, 0x52, 0x61, 0x74,
0x65, 0x4c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x1b, 0x0a, 0x09, 0x6c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b,
0x72, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0d, 0x52, 0x0a, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a,
0x0d, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x03,
0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x53, 0x63, 0x6f,
0x72, 0x65, 0x32, 0x8c, 0x04, 0x0a, 0x0d, 0x4c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x53, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x12, 0x7d, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x61,
0x70, 0x74, 0x6f, 0x70, 0x12, 0x26, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f,
0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c,
0x61, 0x70, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x74,
0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b,
0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x22, 0x11, 0x2f,
0x76, 0x31, 0x2f, 0x6c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x2f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
0x3a, 0x01, 0x2a, 0x12, 0x7c, 0x0a, 0x0c, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x61, 0x70,
0x74, 0x6f, 0x70, 0x12, 0x26, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c,
0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x61,
0x70, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x74, 0x65,
0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e,
0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76,
0x31, 0x2f, 0x6c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x30,
0x01, 0x12, 0x82, 0x01, 0x0a, 0x0b, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x6d, 0x61, 0x67,
0x65, 0x12, 0x25, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70,
0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x6d, 0x61, 0x67,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73,
0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x55, 0x70, 0x6c,
0x6f, 0x61, 0x64, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x6c, 0x61,
0x70, 0x74, 0x6f, 0x70, 0x2f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x69, 0x6d, 0x61, 0x67,
0x65, 0x3a, 0x01, 0x2a, 0x28, 0x01, 0x12, 0x79, 0x0a, 0x0a, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x61,
0x70, 0x74, 0x6f, 0x70, 0x12, 0x24, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f,
0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x52, 0x61, 0x74, 0x65, 0x4c, 0x61, 0x70,
0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x74, 0x65, 0x63,
0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x52,
0x61, 0x74, 0x65, 0x4c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x6c,
0x61, 0x70, 0x74, 0x6f, 0x70, 0x2f, 0x72, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x28, 0x01, 0x30,
0x01, 0x42, 0x29, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e,
0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f,
0x6b, 0x2e, 0x70, 0x62, 0x50, 0x01, 0x5a, 0x04, 0x2e, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x33,
}
var (
file_laptop_service_proto_rawDescOnce sync.Once
file_laptop_service_proto_rawDescData = file_laptop_service_proto_rawDesc
)
func file_laptop_service_proto_rawDescGZIP() []byte {
file_laptop_service_proto_rawDescOnce.Do(func() {
file_laptop_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_laptop_service_proto_rawDescData)
})
return file_laptop_service_proto_rawDescData
}
var file_laptop_service_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
var file_laptop_service_proto_goTypes = []interface{}{
(*CreateLaptopRequest)(nil), // 0: techschool.pcbook.CreateLaptopRequest
(*CreateLaptopResponse)(nil), // 1: techschool.pcbook.CreateLaptopResponse
(*SearchLaptopRequest)(nil), // 2: techschool.pcbook.SearchLaptopRequest
(*SearchLaptopResponse)(nil), // 3: techschool.pcbook.SearchLaptopResponse
(*UploadImageRequest)(nil), // 4: techschool.pcbook.UploadImageRequest
(*ImageInfo)(nil), // 5: techschool.pcbook.ImageInfo
(*UploadImageResponse)(nil), // 6: techschool.pcbook.UploadImageResponse
(*RateLaptopRequest)(nil), // 7: techschool.pcbook.RateLaptopRequest
(*RateLaptopResponse)(nil), // 8: techschool.pcbook.RateLaptopResponse
(*Laptop)(nil), // 9: techschool.pcbook.Laptop
(*Filter)(nil), // 10: techschool.pcbook.Filter
}
var file_laptop_service_proto_depIdxs = []int32{
9, // 0: techschool.pcbook.CreateLaptopRequest.laptop:type_name -> techschool.pcbook.Laptop
10, // 1: techschool.pcbook.SearchLaptopRequest.filter:type_name -> techschool.pcbook.Filter
9, // 2: techschool.pcbook.SearchLaptopResponse.laptop:type_name -> techschool.pcbook.Laptop
5, // 3: techschool.pcbook.UploadImageRequest.info:type_name -> techschool.pcbook.ImageInfo
0, // 4: techschool.pcbook.LaptopService.CreateLaptop:input_type -> techschool.pcbook.CreateLaptopRequest
2, // 5: techschool.pcbook.LaptopService.SearchLaptop:input_type -> techschool.pcbook.SearchLaptopRequest
4, // 6: techschool.pcbook.LaptopService.UploadImage:input_type -> techschool.pcbook.UploadImageRequest
7, // 7: techschool.pcbook.LaptopService.RateLaptop:input_type -> techschool.pcbook.RateLaptopRequest
1, // 8: techschool.pcbook.LaptopService.CreateLaptop:output_type -> techschool.pcbook.CreateLaptopResponse
3, // 9: techschool.pcbook.LaptopService.SearchLaptop:output_type -> techschool.pcbook.SearchLaptopResponse
6, // 10: techschool.pcbook.LaptopService.UploadImage:output_type -> techschool.pcbook.UploadImageResponse
8, // 11: techschool.pcbook.LaptopService.RateLaptop:output_type -> techschool.pcbook.RateLaptopResponse
8, // [8:12] is the sub-list for method output_type
4, // [4:8] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_laptop_service_proto_init() }
func file_laptop_service_proto_init() {
if File_laptop_service_proto != nil {
return
}
file_laptop_message_proto_init()
file_filter_message_proto_init()
if !protoimpl.UnsafeEnabled {
file_laptop_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateLaptopRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_laptop_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateLaptopResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_laptop_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SearchLaptopRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_laptop_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SearchLaptopResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_laptop_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UploadImageRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_laptop_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ImageInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_laptop_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UploadImageResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_laptop_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RateLaptopRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_laptop_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RateLaptopResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_laptop_service_proto_msgTypes[4].OneofWrappers = []interface{}{
(*UploadImageRequest_Info)(nil),
(*UploadImageRequest_ChunkData)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_laptop_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 9,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_laptop_service_proto_goTypes,
DependencyIndexes: file_laptop_service_proto_depIdxs,
MessageInfos: file_laptop_service_proto_msgTypes,
}.Build()
File_laptop_service_proto = out.File
file_laptop_service_proto_rawDesc = nil
file_laptop_service_proto_goTypes = nil
file_laptop_service_proto_depIdxs = nil
}
================================================
FILE: pb/laptop_service.pb.gw.go
================================================
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
// source: laptop_service.proto
/*
Package pb is a reverse proxy.
It translates gRPC into RESTful JSON APIs.
*/
package pb
import (
"context"
"io"
"net/http"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
)
// Suppress "imported and not used" errors
var _ codes.Code
var _ io.Reader
var _ status.Status
var _ = runtime.String
var _ = utilities.NewDoubleArray
var _ = metadata.Join
func request_LaptopService_CreateLaptop_0(ctx context.Context, marshaler runtime.Marshaler, client LaptopServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq CreateLaptopRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.CreateLaptop(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_LaptopService_CreateLaptop_0(ctx context.Context, marshaler runtime.Marshaler, server LaptopServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq CreateLaptopRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
if berr != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
}
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.CreateLaptop(ctx, &protoReq)
return msg, metadata, err
}
var (
filter_LaptopService_SearchLaptop_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
)
func request_LaptopService_SearchLaptop_0(ctx context.Context, marshaler runtime.Marshaler, client LaptopServiceClient, req *http.Request, pathParams map[string]string) (LaptopService_SearchLaptopClient, runtime.ServerMetadata, error) {
var protoReq SearchLaptopRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_LaptopService_SearchLaptop_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
stream, err := client.SearchLaptop(ctx, &protoReq)
if err != nil {
return nil, metadata, err
}
header, err := stream.Header()
if err != nil {
return nil, metadata, err
}
metadata.HeaderMD = header
return stream, metadata, nil
}
func request_LaptopService_UploadImage_0(ctx context.Context, marshaler runtime.Marshaler, client LaptopServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var metadata runtime.ServerMetadata
stream, err := client.UploadImage(ctx)
if err != nil {
grpclog.Infof("Failed to start streaming: %v", err)
return nil, metadata, err
}
dec := marshaler.NewDecoder(req.Body)
for {
var protoReq UploadImageRequest
err = dec.Decode(&protoReq)
if err == io.EOF {
break
}
if err != nil {
grpclog.Infof("Failed to decode request: %v", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err = stream.Send(&protoReq); err != nil {
if err == io.EOF {
break
}
grpclog.Infof("Failed to send request: %v", err)
return nil, metadata, err
}
}
if err := stream.CloseSend(); err != nil {
grpclog.Infof("Failed to terminate client stream: %v", err)
return nil, metadata, err
}
header, err := stream.Header()
if err != nil {
grpclog.Infof("Failed to get header from client: %v", err)
return nil, metadata, err
}
metadata.HeaderMD = header
msg, err := stream.CloseAndRecv()
metadata.TrailerMD = stream.Trailer()
return msg, metadata, err
}
func request_LaptopService_RateLaptop_0(ctx context.Context, marshaler runtime.Marshaler, client LaptopServiceClient, req *http.Request, pathParams map[string]string) (LaptopService_RateLaptopClient, runtime.ServerMetadata, error) {
var metadata runtime.ServerMetadata
stream, err := client.RateLaptop(ctx)
if err != nil {
grpclog.Infof("Failed to start streaming: %v", err)
return nil, metadata, err
}
dec := marshaler.NewDecoder(req.Body)
handleSend := func() error {
var protoReq RateLaptopRequest
err := dec.Decode(&protoReq)
if err == io.EOF {
return err
}
if err != nil {
grpclog.Infof("Failed to decode request: %v", err)
return err
}
if err := stream.Send(&protoReq); err != nil {
grpclog.Infof("Failed to send request: %v", err)
return err
}
return nil
}
if err := handleSend(); err != nil {
if cerr := stream.CloseSend(); cerr != nil {
grpclog.Infof("Failed to terminate client stream: %v", cerr)
}
if err == io.EOF {
return stream, metadata, nil
}
return nil, metadata, err
}
go func() {
for {
if err := handleSend(); err != nil {
break
}
}
if err := stream.CloseSend(); err != nil {
grpclog.Infof("Failed to terminate client stream: %v", err)
}
}()
header, err := stream.Header()
if err != nil {
grpclog.Infof("Failed to get header from client: %v", err)
return nil, metadata, err
}
metadata.HeaderMD = header
return stream, metadata, nil
}
// RegisterLaptopServiceHandlerServer registers the http handlers for service LaptopService to "mux".
// UnaryRPC :call LaptopServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterLaptopServiceHandlerFromEndpoint instead.
func RegisterLaptopServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server LaptopServiceServer) error {
mux.Handle("POST", pattern_LaptopService_CreateLaptop_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/techschool.pcbook.LaptopService/CreateLaptop")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_LaptopService_CreateLaptop_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_LaptopService_CreateLaptop_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_LaptopService_SearchLaptop_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport")
_, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
})
mux.Handle("POST", pattern_LaptopService_UploadImage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport")
_, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
})
mux.Handle("POST", pattern_LaptopService_RateLaptop_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport")
_, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
})
return nil
}
// RegisterLaptopServiceHandlerFromEndpoint is same as RegisterLaptopServiceHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterLaptopServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
conn, err := grpc.Dial(endpoint, opts...)
if err != nil {
return err
}
defer func() {
if err != nil {
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
return
}
go func() {
<-ctx.Done()
if cerr := conn.Close(); cerr != nil {
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
}
}()
}()
return RegisterLaptopServiceHandler(ctx, mux, conn)
}
// RegisterLaptopServiceHandler registers the http handlers for service LaptopService to "mux".
// The handlers forward requests to the grpc endpoint over "conn".
func RegisterLaptopServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
return RegisterLaptopServiceHandlerClient(ctx, mux, NewLaptopServiceClient(conn))
}
// RegisterLaptopServiceHandlerClient registers the http handlers for service LaptopService
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "LaptopServiceClient".
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "LaptopServiceClient"
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
// "LaptopServiceClient" to call the correct interceptors.
func RegisterLaptopServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client LaptopServiceClient) error {
mux.Handle("POST", pattern_LaptopService_CreateLaptop_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/techschool.pcbook.LaptopService/CreateLaptop")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_LaptopService_CreateLaptop_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_LaptopService_CreateLaptop_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_LaptopService_SearchLaptop_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/techschool.pcbook.LaptopService/SearchLaptop")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_LaptopService_SearchLaptop_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_LaptopService_SearchLaptop_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_LaptopService_UploadImage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/techschool.pcbook.LaptopService/UploadImage")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_LaptopService_UploadImage_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_LaptopService_UploadImage_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_LaptopService_RateLaptop_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/techschool.pcbook.LaptopService/RateLaptop")
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_LaptopService_RateLaptop_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_LaptopService_RateLaptop_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...)
})
return nil
}
var (
pattern_LaptopService_CreateLaptop_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "laptop", "create"}, ""))
pattern_LaptopService_SearchLaptop_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "laptop", "search"}, ""))
pattern_LaptopService_UploadImage_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "laptop", "upload_image"}, ""))
pattern_LaptopService_RateLaptop_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "laptop", "rate"}, ""))
)
var (
forward_LaptopService_CreateLaptop_0 = runtime.ForwardResponseMessage
forward_LaptopService_SearchLaptop_0 = runtime.ForwardResponseStream
forward_LaptopService_UploadImage_0 = runtime.ForwardResponseMessage
forward_LaptopService_RateLaptop_0 = runtime.ForwardResponseStream
)
================================================
FILE: pb/laptop_service_grpc.pb.go
================================================
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package pb
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// LaptopServiceClient is the client API for LaptopService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type LaptopServiceClient interface {
CreateLaptop(ctx context.Context, in *CreateLaptopRequest, opts ...grpc.CallOption) (*CreateLaptopResponse, error)
SearchLaptop(ctx context.Context, in *SearchLaptopRequest, opts ...grpc.CallOption) (LaptopService_SearchLaptopClient, error)
UploadImage(ctx context.Context, opts ...grpc.CallOption) (LaptopService_UploadImageClient, error)
RateLaptop(ctx context.Context, opts ...grpc.CallOption) (LaptopService_RateLaptopClient, error)
}
type laptopServiceClient struct {
cc grpc.ClientConnInterface
}
func NewLaptopServiceClient(cc grpc.ClientConnInterface) LaptopServiceClient {
return &laptopServiceClient{cc}
}
func (c *laptopServiceClient) CreateLaptop(ctx context.Context, in *CreateLaptopRequest, opts ...grpc.CallOption) (*CreateLaptopResponse, error) {
out := new(CreateLaptopResponse)
err := c.cc.Invoke(ctx, "/techschool.pcbook.LaptopService/CreateLaptop", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *laptopServiceClient) SearchLaptop(ctx context.Context, in *SearchLaptopRequest, opts ...grpc.CallOption) (LaptopService_SearchLaptopClient, error) {
stream, err := c.cc.NewStream(ctx, &LaptopService_ServiceDesc.Streams[0], "/techschool.pcbook.LaptopService/SearchLaptop", opts...)
if err != nil {
return nil, err
}
x := &laptopServiceSearchLaptopClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type LaptopService_SearchLaptopClient interface {
Recv() (*SearchLaptopResponse, error)
grpc.ClientStream
}
type laptopServiceSearchLaptopClient struct {
grpc.ClientStream
}
func (x *laptopServiceSearchLaptopClient) Recv() (*SearchLaptopResponse, error) {
m := new(SearchLaptopResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *laptopServiceClient) UploadImage(ctx context.Context, opts ...grpc.CallOption) (LaptopService_UploadImageClient, error) {
stream, err := c.cc.NewStream(ctx, &LaptopService_ServiceDesc.Streams[1], "/techschool.pcbook.LaptopService/UploadImage", opts...)
if err != nil {
return nil, err
}
x := &laptopServiceUploadImageClient{stream}
return x, nil
}
type LaptopService_UploadImageClient interface {
Send(*UploadImageRequest) error
CloseAndRecv() (*UploadImageResponse, error)
grpc.ClientStream
}
type laptopServiceUploadImageClient struct {
grpc.ClientStream
}
func (x *laptopServiceUploadImageClient) Send(m *UploadImageRequest) error {
return x.ClientStream.SendMsg(m)
}
func (x *laptopServiceUploadImageClient) CloseAndRecv() (*UploadImageResponse, error) {
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
m := new(UploadImageResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *laptopServiceClient) RateLaptop(ctx context.Context, opts ...grpc.CallOption) (LaptopService_RateLaptopClient, error) {
stream, err := c.cc.NewStream(ctx, &LaptopService_ServiceDesc.Streams[2], "/techschool.pcbook.LaptopService/RateLaptop", opts...)
if err != nil {
return nil, err
}
x := &laptopServiceRateLaptopClient{stream}
return x, nil
}
type LaptopService_RateLaptopClient interface {
Send(*RateLaptopRequest) error
Recv() (*RateLaptopResponse, error)
grpc.ClientStream
}
type laptopServiceRateLaptopClient struct {
grpc.ClientStream
}
func (x *laptopServiceRateLaptopClient) Send(m *RateLaptopRequest) error {
return x.ClientStream.SendMsg(m)
}
func (x *laptopServiceRateLaptopClient) Recv() (*RateLaptopResponse, error) {
m := new(RateLaptopResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// LaptopServiceServer is the server API for LaptopService service.
// All implementations must embed UnimplementedLaptopServiceServer
// for forward compatibility
type LaptopServiceServer interface {
CreateLaptop(context.Context, *CreateLaptopRequest) (*CreateLaptopResponse, error)
SearchLaptop(*SearchLaptopRequest, LaptopService_SearchLaptopServer) error
UploadImage(LaptopService_UploadImageServer) error
RateLaptop(LaptopService_RateLaptopServer) error
mustEmbedUnimplementedLaptopServiceServer()
}
// UnimplementedLaptopServiceServer must be embedded to have forward compatible implementations.
type UnimplementedLaptopServiceServer struct {
}
func (UnimplementedLaptopServiceServer) CreateLaptop(context.Context, *CreateLaptopRequest) (*CreateLaptopResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateLaptop not implemented")
}
func (UnimplementedLaptopServiceServer) SearchLaptop(*SearchLaptopRequest, LaptopService_SearchLaptopServer) error {
return status.Errorf(codes.Unimplemented, "method SearchLaptop not implemented")
}
func (UnimplementedLaptopServiceServer) UploadImage(LaptopService_UploadImageServer) error {
return status.Errorf(codes.Unimplemented, "method UploadImage not implemented")
}
func (UnimplementedLaptopServiceServer) RateLaptop(LaptopService_RateLaptopServer) error {
return status.Errorf(codes.Unimplemented, "method RateLaptop not implemented")
}
func (UnimplementedLaptopServiceServer) mustEmbedUnimplementedLaptopServiceServer() {}
// UnsafeLaptopServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to LaptopServiceServer will
// result in compilation errors.
type UnsafeLaptopServiceServer interface {
mustEmbedUnimplementedLaptopServiceServer()
}
func RegisterLaptopServiceServer(s grpc.ServiceRegistrar, srv LaptopServiceServer) {
s.RegisterService(&LaptopService_ServiceDesc, srv)
}
func _LaptopService_CreateLaptop_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateLaptopRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(LaptopServiceServer).CreateLaptop(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/techschool.pcbook.LaptopService/CreateLaptop",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(LaptopServiceServer).CreateLaptop(ctx, req.(*CreateLaptopRequest))
}
return interceptor(ctx, in, info, handler)
}
func _LaptopService_SearchLaptop_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(SearchLaptopRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(LaptopServiceServer).SearchLaptop(m, &laptopServiceSearchLaptopServer{stream})
}
type LaptopService_SearchLaptopServer interface {
Send(*SearchLaptopResponse) error
grpc.ServerStream
}
type laptopServiceSearchLaptopServer struct {
grpc.ServerStream
}
func (x *laptopServiceSearchLaptopServer) Send(m *SearchLaptopResponse) error {
return x.ServerStream.SendMsg(m)
}
func _LaptopService_UploadImage_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(LaptopServiceServer).UploadImage(&laptopServiceUploadImageServer{stream})
}
type LaptopService_UploadImageServer interface {
SendAndClose(*UploadImageResponse) error
Recv() (*UploadImageRequest, error)
grpc.ServerStream
}
type laptopServiceUploadImageServer struct {
grpc.ServerStream
}
func (x *laptopServiceUploadImageServer) SendAndClose(m *UploadImageResponse) error {
return x.ServerStream.SendMsg(m)
}
func (x *laptopServiceUploadImageServer) Recv() (*UploadImageRequest, error) {
m := new(UploadImageRequest)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func _LaptopService_RateLaptop_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(LaptopServiceServer).RateLaptop(&laptopServiceRateLaptopServer{stream})
}
type LaptopService_RateLaptopServer interface {
Send(*RateLaptopResponse) error
Recv() (*RateLaptopRequest, error)
grpc.ServerStream
}
type laptopServiceRateLaptopServer struct {
grpc.ServerStream
}
func (x *laptopServiceRateLaptopServer) Send(m *RateLaptopResponse) error {
return x.ServerStream.SendMsg(m)
}
func (x *laptopServiceRateLaptopServer) Recv() (*RateLaptopRequest, error) {
m := new(RateLaptopRequest)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// LaptopService_ServiceDesc is the grpc.ServiceDesc for LaptopService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var LaptopService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "techschool.pcbook.LaptopService",
HandlerType: (*LaptopServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "CreateLaptop",
Handler: _LaptopService_CreateLaptop_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "SearchLaptop",
Handler: _LaptopService_SearchLaptop_Handler,
ServerStreams: true,
},
{
StreamName: "UploadImage",
Handler: _LaptopService_UploadImage_Handler,
ClientStreams: true,
},
{
StreamName: "RateLaptop",
Handler: _LaptopService_RateLaptop_Handler,
ServerStreams: true,
ClientStreams: true,
},
},
Metadata: "laptop_service.proto",
}
================================================
FILE: pb/memory_message.pb.go
================================================
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0
// protoc v3.14.0
// source: memory_message.proto
package pb
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto package is being used.
const _ = proto.ProtoPackageIsVersion4
type Memory_Unit int32
const (
Memory_UNKNOWN Memory_Unit = 0
Memory_BIT Memory_Unit = 1
Memory_BYTE Memory_Unit = 2
Memory_KILOBYTE Memory_Unit = 3
Memory_MEGABYTE Memory_Unit = 4
Memory_GIGABYTE Memory_Unit = 5
Memory_TERABYTE Memory_Unit = 6
)
// Enum value maps for Memory_Unit.
var (
Memory_Unit_name = map[int32]string{
0: "UNKNOWN",
1: "BIT",
2: "BYTE",
3: "KILOBYTE",
4: "MEGABYTE",
5: "GIGABYTE",
6: "TERABYTE",
}
Memory_Unit_value = map[string]int32{
"UNKNOWN": 0,
"BIT": 1,
"BYTE": 2,
"KILOBYTE": 3,
"MEGABYTE": 4,
"GIGABYTE": 5,
"TERABYTE": 6,
}
)
func (x Memory_Unit) Enum() *Memory_Unit {
p := new(Memory_Unit)
*p = x
return p
}
func (x Memory_Unit) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (Memory_Unit) Descriptor() protoreflect.EnumDescriptor {
return file_memory_message_proto_enumTypes[0].Descriptor()
}
func (Memory_Unit) Type() protoreflect.EnumType {
return &file_memory_message_proto_enumTypes[0]
}
func (x Memory_Unit) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use Memory_Unit.Descriptor instead.
func (Memory_Unit) EnumDescriptor() ([]byte, []int) {
return file_memory_message_proto_rawDescGZIP(), []int{0, 0}
}
type Memory struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Value uint64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
Unit Memory_Unit `protobuf:"varint,2,opt,name=unit,proto3,enum=techschool.pcbook.Memory_Unit" json:"unit,omitempty"`
}
func (x *Memory) Reset() {
*x = Memory{}
if protoimpl.UnsafeEnabled {
mi := &file_memory_message_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Memory) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Memory) ProtoMessage() {}
func (x *Memory) ProtoReflect() protoreflect.Message {
mi := &file_memory_message_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Memory.ProtoReflect.Descriptor instead.
func (*Memory) Descriptor() ([]byte, []int) {
return file_memory_message_proto_rawDescGZIP(), []int{0}
}
func (x *Memory) GetValue() uint64 {
if x != nil {
return x.Value
}
return 0
}
func (x *Memory) GetUnit() Memory_Unit {
if x != nil {
return x.Unit
}
return Memory_UNKNOWN
}
var File_memory_message_proto protoreflect.FileDescriptor
var file_memory_message_proto_rawDesc = []byte{
0x0a, 0x14, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x74, 0x65, 0x63, 0x68, 0x73, 0x63, 0x68, 0x6f,
0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x22, 0xb2, 0x01, 0x0a, 0x06, 0x4d, 0x65,
0x6d, 0x6f, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x32, 0x0a, 0x04, 0x75, 0x6e,
0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x63, 0x68, 0x73,
0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x4d, 0x65, 0x6d,
0x6f, 0x72, 0x79, 0x2e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x22, 0x5e,
0x0a, 0x04, 0x55, 0x6e, 0x69, 0x74, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57,
0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x42, 0x49, 0x54, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04,
0x42, 0x59, 0x54, 0x45, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x4b, 0x49, 0x4c, 0x4f, 0x42, 0x59,
0x54, 0x45, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x4d, 0x45, 0x47, 0x41, 0x42, 0x59, 0x54, 0x45,
0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x47, 0x49, 0x47, 0x41, 0x42, 0x59, 0x54, 0x45, 0x10, 0x05,
0x12, 0x0c, 0x0a, 0x08, 0x54, 0x45, 0x52, 0x41, 0x42, 0x59, 0x54, 0x45, 0x10, 0x06, 0x42, 0x29,
0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x74, 0x65, 0x63,
0x68, 0x73, 0x63, 0x68, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x63, 0x62, 0x6f, 0x6f, 0x6b, 0x2e, 0x70,
0x62, 0x50, 0x01, 0x5a, 0x04, 0x2e, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var (
file_memory_message_proto_rawDescOnce sync.Once
file_memory_message_proto_rawDescData = file_memory_message_proto_rawDesc
)
func file_memory_message_proto_rawDescGZIP() []byte {
file_memory_message_proto_rawDescOnce.Do(func() {
file_memory_message_proto_rawDescData = protoimpl.X.CompressGZIP(file_memory_message_proto_rawDescData)
})
return file_memory_message_proto_rawDescData
}
var file_memory_message_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_memory_message_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_memory_message_proto_goTypes = []interface{}{
(Memory_Unit)(0), // 0: techschool.pcbook.Memory.Unit
(*Memory)(nil), // 1: techschool.pcbook.Memory
}
var file_memory_message_proto_depIdxs = []int32{
0, // 0: techschool.pcbook.Memory.unit:type_name -> techschool.pcbook.Memory.Unit
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_memory_message_proto_init() }
func file_memory_message_proto_init() {
if File_memory_message_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_memory_message_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Memory); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_memory_message_proto_rawDesc,
NumEnums: 1,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_memory_message_proto_goTypes,
DependencyIndexes: file_memory_message_proto_depIdxs,
EnumInfos: file_memory_message_proto_enumTypes,
MessageInfos: file_memory_message_proto_msgTypes,
}.Build()
File_memory_message_proto = out.File
file_memory_message_proto_rawDesc = nil
file_memory_message_proto_goTypes = nil
file_memory_message_proto_depIdxs = nil
}
================================================
FILE: pb/processor_message.pb.go
================================================
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.25.0
// protoc v3.14.0
// source: processor_message.proto
package pb
import (
proto "github.com/golang/protobuf/proto"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// This is a compile-time assertion that a sufficiently up-to-date version
// of the legacy proto packa
gitextract_gwqh_f95/
├── .github/
│ └── workflows/
│ └── ci.yml
├── Makefile
├── README.md
├── cert/
│ ├── ca-cert.pem
│ ├── ca-cert.srl
│ ├── ca-key.pem
│ ├── client-cert.pem
│ ├── client-ext.cnf
│ ├── client-key.pem
│ ├── client-req.pem
│ ├── gen.sh
│ ├── server-cert.pem
│ ├── server-ext.cnf
│ ├── server-key.pem
│ └── server-req.pem
├── client/
│ ├── auth_client.go
│ ├── auth_interceptor.go
│ └── laptop_client.go
├── cmd/
│ ├── client/
│ │ └── main.go
│ └── server/
│ └── main.go
├── go.mod
├── go.sum
├── img/
│ └── .gitkeep
├── nginx.conf
├── pb/
│ ├── auth_service.pb.go
│ ├── auth_service.pb.gw.go
│ ├── auth_service_grpc.pb.go
│ ├── filter_message.pb.go
│ ├── keyboard_message.pb.go
│ ├── laptop_message.pb.go
│ ├── laptop_service.pb.go
│ ├── laptop_service.pb.gw.go
│ ├── laptop_service_grpc.pb.go
│ ├── memory_message.pb.go
│ ├── processor_message.pb.go
│ ├── screen_message.pb.go
│ └── storage_message.pb.go
├── proto/
│ ├── auth_service.proto
│ ├── filter_message.proto
│ ├── google/
│ │ ├── api/
│ │ │ ├── annotations.proto
│ │ │ ├── http.proto
│ │ │ └── httpbody.proto
│ │ └── rpc/
│ │ ├── code.proto
│ │ ├── error_details.proto
│ │ └── status.proto
│ ├── keyboard_message.proto
│ ├── laptop_message.proto
│ ├── laptop_service.proto
│ ├── memory_message.proto
│ ├── processor_message.proto
│ ├── screen_message.proto
│ └── storage_message.proto
├── sample/
│ ├── laptop.go
│ └── random.go
├── serializer/
│ ├── file.go
│ ├── file_test.go
│ └── json.go
├── service/
│ ├── auth_interceptor.go
│ ├── auth_server.go
│ ├── image_store.go
│ ├── jwt_manager.go
│ ├── laptop_client_test.go
│ ├── laptop_server.go
│ ├── laptop_server_test.go
│ ├── laptop_store.go
│ ├── rating_store.go
│ ├── user.go
│ └── user_store.go
├── swagger/
│ ├── auth_service.swagger.json
│ ├── filter_message.swagger.json
│ ├── keyboard_message.swagger.json
│ ├── laptop_message.swagger.json
│ ├── laptop_service.swagger.json
│ ├── memory_message.swagger.json
│ ├── processor_message.swagger.json
│ ├── screen_message.swagger.json
│ └── storage_message.swagger.json
└── tmp/
└── laptop.json
SYMBOL INDEX (487 symbols across 34 files)
FILE: client/auth_client.go
type AuthClient (line 12) | type AuthClient struct
method Login (line 25) | func (client *AuthClient) Login() (string, error) {
function NewAuthClient (line 19) | func NewAuthClient(cc *grpc.ClientConn, username string, password string...
FILE: client/auth_interceptor.go
type AuthInterceptor (line 13) | type AuthInterceptor struct
method Unary (line 39) | func (interceptor *AuthInterceptor) Unary() grpc.UnaryClientInterceptor {
method Stream (line 59) | func (interceptor *AuthInterceptor) Stream() grpc.StreamClientIntercep...
method attachToken (line 78) | func (interceptor *AuthInterceptor) attachToken(ctx context.Context) c...
method scheduleRefreshToken (line 82) | func (interceptor *AuthInterceptor) scheduleRefreshToken(refreshDurati...
method refreshToken (line 104) | func (interceptor *AuthInterceptor) refreshToken() error {
function NewAuthInterceptor (line 20) | func NewAuthInterceptor(
FILE: client/laptop_client.go
type LaptopClient (line 20) | type LaptopClient struct
method CreateLaptop (line 31) | func (laptopClient *LaptopClient) CreateLaptop(laptop *pb.Laptop) {
method SearchLaptop (line 56) | func (laptopClient *LaptopClient) SearchLaptop(filter *pb.Filter) {
method UploadImage (line 89) | func (laptopClient *LaptopClient) UploadImage(laptopID string, imagePa...
method RateLaptop (line 151) | func (laptopClient *LaptopClient) RateLaptop(laptopIDs []string, score...
function NewLaptopClient (line 25) | func NewLaptopClient(cc *grpc.ClientConn) *LaptopClient {
FILE: cmd/client/main.go
function testCreateLaptop (line 20) | func testCreateLaptop(laptopClient *client.LaptopClient) {
function testSearchLaptop (line 24) | func testSearchLaptop(laptopClient *client.LaptopClient) {
function testUploadImage (line 39) | func testUploadImage(laptopClient *client.LaptopClient) {
function testRateLaptop (line 45) | func testRateLaptop(laptopClient *client.LaptopClient) {
constant username (line 77) | username = "admin1"
constant password (line 78) | password = "secret"
constant refreshDuration (line 79) | refreshDuration = 30 * time.Second
function authMethods (line 82) | func authMethods() map[string]bool {
function loadTLSCredentials (line 92) | func loadTLSCredentials() (credentials.TransportCredentials, error) {
function main (line 119) | func main() {
FILE: cmd/server/main.go
function seedUsers (line 23) | func seedUsers(userStore service.UserStore) error {
function createUser (line 31) | func createUser(userStore service.UserStore, username, password, role st...
constant secretKey (line 40) | secretKey = "secret"
constant tokenDuration (line 41) | tokenDuration = 15 * time.Minute
constant serverCertFile (line 45) | serverCertFile = "cert/server-cert.pem"
constant serverKeyFile (line 46) | serverKeyFile = "cert/server-key.pem"
constant clientCACertFile (line 47) | clientCACertFile = "cert/ca-cert.pem"
function accessibleRoles (line 50) | func accessibleRoles() map[string][]string {
function loadTLSCredentials (line 60) | func loadTLSCredentials() (credentials.TransportCredentials, error) {
function runGRPCServer (line 88) | func runGRPCServer(
function runRESTServer (line 120) | func runRESTServer(
function main (line 157) | func main() {
FILE: pb/auth_service.pb.go
constant _ (line 20) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 22) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
constant _ (line 27) | _ = proto.ProtoPackageIsVersion4
type LoginRequest (line 29) | type LoginRequest struct
method Reset (line 38) | func (x *LoginRequest) Reset() {
method String (line 47) | func (x *LoginRequest) String() string {
method ProtoMessage (line 51) | func (*LoginRequest) ProtoMessage() {}
method ProtoReflect (line 53) | func (x *LoginRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 66) | func (*LoginRequest) Descriptor() ([]byte, []int) {
method GetUsername (line 70) | func (x *LoginRequest) GetUsername() string {
method GetPassword (line 77) | func (x *LoginRequest) GetPassword() string {
type LoginResponse (line 84) | type LoginResponse struct
method Reset (line 92) | func (x *LoginResponse) Reset() {
method String (line 101) | func (x *LoginResponse) String() string {
method ProtoMessage (line 105) | func (*LoginResponse) ProtoMessage() {}
method ProtoReflect (line 107) | func (x *LoginResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 120) | func (*LoginResponse) Descriptor() ([]byte, []int) {
method GetAccessToken (line 124) | func (x *LoginResponse) GetAccessToken() string {
function file_auth_service_proto_rawDescGZIP (line 164) | func file_auth_service_proto_rawDescGZIP() []byte {
function init (line 186) | func init() { file_auth_service_proto_init() }
function file_auth_service_proto_init (line 187) | func file_auth_service_proto_init() {
FILE: pb/auth_service.pb.gw.go
function request_AuthService_Login_0 (line 34) | func request_AuthService_Login_0(ctx context.Context, marshaler runtime....
function local_request_AuthService_Login_0 (line 51) | func local_request_AuthService_Login_0(ctx context.Context, marshaler ru...
function RegisterAuthServiceHandlerServer (line 72) | func RegisterAuthServiceHandlerServer(ctx context.Context, mux *runtime....
function RegisterAuthServiceHandlerFromEndpoint (line 102) | func RegisterAuthServiceHandlerFromEndpoint(ctx context.Context, mux *ru...
function RegisterAuthServiceHandler (line 127) | func RegisterAuthServiceHandler(ctx context.Context, mux *runtime.ServeM...
function RegisterAuthServiceHandlerClient (line 136) | func RegisterAuthServiceHandlerClient(ctx context.Context, mux *runtime....
FILE: pb/auth_service_grpc.pb.go
constant _ (line 15) | _ = grpc.SupportPackageIsVersion7
type AuthServiceClient (line 20) | type AuthServiceClient interface
type authServiceClient (line 24) | type authServiceClient struct
method Login (line 32) | func (c *authServiceClient) Login(ctx context.Context, in *LoginReques...
function NewAuthServiceClient (line 28) | func NewAuthServiceClient(cc grpc.ClientConnInterface) AuthServiceClient {
type AuthServiceServer (line 44) | type AuthServiceServer interface
type UnimplementedAuthServiceServer (line 50) | type UnimplementedAuthServiceServer struct
method Login (line 53) | func (UnimplementedAuthServiceServer) Login(context.Context, *LoginReq...
method mustEmbedUnimplementedAuthServiceServer (line 56) | func (UnimplementedAuthServiceServer) mustEmbedUnimplementedAuthServic...
type UnsafeAuthServiceServer (line 61) | type UnsafeAuthServiceServer interface
function RegisterAuthServiceServer (line 65) | func RegisterAuthServiceServer(s grpc.ServiceRegistrar, srv AuthServiceS...
function _AuthService_Login_Handler (line 69) | func _AuthService_Login_Handler(srv interface{}, ctx context.Context, de...
FILE: pb/filter_message.pb.go
constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
constant _ (line 26) | _ = proto.ProtoPackageIsVersion4
type Filter (line 28) | type Filter struct
method Reset (line 39) | func (x *Filter) Reset() {
method String (line 48) | func (x *Filter) String() string {
method ProtoMessage (line 52) | func (*Filter) ProtoMessage() {}
method ProtoReflect (line 54) | func (x *Filter) ProtoReflect() protoreflect.Message {
method Descriptor (line 67) | func (*Filter) Descriptor() ([]byte, []int) {
method GetMaxPriceUsd (line 71) | func (x *Filter) GetMaxPriceUsd() float64 {
method GetMinCpuCores (line 78) | func (x *Filter) GetMinCpuCores() uint32 {
method GetMinCpuGhz (line 85) | func (x *Filter) GetMinCpuGhz() float64 {
method GetMinRam (line 92) | func (x *Filter) GetMinRam() *Memory {
function file_filter_message_proto_rawDescGZIP (line 127) | func file_filter_message_proto_rawDescGZIP() []byte {
function init (line 148) | func init() { file_filter_message_proto_init() }
function file_filter_message_proto_init (line 149) | func file_filter_message_proto_init() {
FILE: pb/keyboard_message.pb.go
constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
constant _ (line 26) | _ = proto.ProtoPackageIsVersion4
type Keyboard_Layout (line 28) | type Keyboard_Layout
method Enum (line 53) | func (x Keyboard_Layout) Enum() *Keyboard_Layout {
method String (line 59) | func (x Keyboard_Layout) String() string {
method Descriptor (line 63) | func (Keyboard_Layout) Descriptor() protoreflect.EnumDescriptor {
method Type (line 67) | func (Keyboard_Layout) Type() protoreflect.EnumType {
method Number (line 71) | func (x Keyboard_Layout) Number() protoreflect.EnumNumber {
method EnumDescriptor (line 76) | func (Keyboard_Layout) EnumDescriptor() ([]byte, []int) {
constant Keyboard_UNKNOWN (line 31) | Keyboard_UNKNOWN Keyboard_Layout = 0
constant Keyboard_QWERTY (line 32) | Keyboard_QWERTY Keyboard_Layout = 1
constant Keyboard_QWERTZ (line 33) | Keyboard_QWERTZ Keyboard_Layout = 2
constant Keyboard_AZERTY (line 34) | Keyboard_AZERTY Keyboard_Layout = 3
type Keyboard (line 80) | type Keyboard struct
method Reset (line 89) | func (x *Keyboard) Reset() {
method String (line 98) | func (x *Keyboard) String() string {
method ProtoMessage (line 102) | func (*Keyboard) ProtoMessage() {}
method ProtoReflect (line 104) | func (x *Keyboard) ProtoReflect() protoreflect.Message {
method Descriptor (line 117) | func (*Keyboard) Descriptor() ([]byte, []int) {
method GetLayout (line 121) | func (x *Keyboard) GetLayout() Keyboard_Layout {
method GetBacklit (line 128) | func (x *Keyboard) GetBacklit() bool {
function file_keyboard_message_proto_rawDescGZIP (line 161) | func file_keyboard_message_proto_rawDescGZIP() []byte {
function init (line 183) | func init() { file_keyboard_message_proto_init() }
function file_keyboard_message_proto_init (line 184) | func file_keyboard_message_proto_init() {
FILE: pb/laptop_message.pb.go
constant _ (line 20) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 22) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
constant _ (line 27) | _ = proto.ProtoPackageIsVersion4
type Laptop (line 29) | type Laptop struct
method Reset (line 52) | func (x *Laptop) Reset() {
method String (line 61) | func (x *Laptop) String() string {
method ProtoMessage (line 65) | func (*Laptop) ProtoMessage() {}
method ProtoReflect (line 67) | func (x *Laptop) ProtoReflect() protoreflect.Message {
method Descriptor (line 80) | func (*Laptop) Descriptor() ([]byte, []int) {
method GetId (line 84) | func (x *Laptop) GetId() string {
method GetBrand (line 91) | func (x *Laptop) GetBrand() string {
method GetName (line 98) | func (x *Laptop) GetName() string {
method GetCpu (line 105) | func (x *Laptop) GetCpu() *CPU {
method GetRam (line 112) | func (x *Laptop) GetRam() *Memory {
method GetGpus (line 119) | func (x *Laptop) GetGpus() []*GPU {
method GetStorages (line 126) | func (x *Laptop) GetStorages() []*Storage {
method GetScreen (line 133) | func (x *Laptop) GetScreen() *Screen {
method GetKeyboard (line 140) | func (x *Laptop) GetKeyboard() *Keyboard {
method GetWeight (line 147) | func (m *Laptop) GetWeight() isLaptop_Weight {
method GetWeightKg (line 154) | func (x *Laptop) GetWeightKg() float64 {
method GetWeightLb (line 161) | func (x *Laptop) GetWeightLb() float64 {
method GetPriceUsd (line 168) | func (x *Laptop) GetPriceUsd() float64 {
method GetReleaseYear (line 175) | func (x *Laptop) GetReleaseYear() uint32 {
method GetUpdatedAt (line 182) | func (x *Laptop) GetUpdatedAt() *timestamppb.Timestamp {
type isLaptop_Weight (line 189) | type isLaptop_Weight interface
type Laptop_WeightKg (line 193) | type Laptop_WeightKg struct
method isLaptop_Weight (line 201) | func (*Laptop_WeightKg) isLaptop_Weight() {}
type Laptop_WeightLb (line 197) | type Laptop_WeightLb struct
method isLaptop_Weight (line 203) | func (*Laptop_WeightLb) isLaptop_Weight() {}
function file_laptop_message_proto_rawDescGZIP (line 265) | func file_laptop_message_proto_rawDescGZIP() []byte {
function init (line 298) | func init() { file_laptop_message_proto_init() }
function file_laptop_message_proto_init (line 299) | func file_laptop_message_proto_init() {
FILE: pb/laptop_service.pb.go
constant _ (line 20) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 22) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
constant _ (line 27) | _ = proto.ProtoPackageIsVersion4
type CreateLaptopRequest (line 29) | type CreateLaptopRequest struct
method Reset (line 37) | func (x *CreateLaptopRequest) Reset() {
method String (line 46) | func (x *CreateLaptopRequest) String() string {
method ProtoMessage (line 50) | func (*CreateLaptopRequest) ProtoMessage() {}
method ProtoReflect (line 52) | func (x *CreateLaptopRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 65) | func (*CreateLaptopRequest) Descriptor() ([]byte, []int) {
method GetLaptop (line 69) | func (x *CreateLaptopRequest) GetLaptop() *Laptop {
type CreateLaptopResponse (line 76) | type CreateLaptopResponse struct
method Reset (line 84) | func (x *CreateLaptopResponse) Reset() {
method String (line 93) | func (x *CreateLaptopResponse) String() string {
method ProtoMessage (line 97) | func (*CreateLaptopResponse) ProtoMessage() {}
method ProtoReflect (line 99) | func (x *CreateLaptopResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 112) | func (*CreateLaptopResponse) Descriptor() ([]byte, []int) {
method GetId (line 116) | func (x *CreateLaptopResponse) GetId() string {
type SearchLaptopRequest (line 123) | type SearchLaptopRequest struct
method Reset (line 131) | func (x *SearchLaptopRequest) Reset() {
method String (line 140) | func (x *SearchLaptopRequest) String() string {
method ProtoMessage (line 144) | func (*SearchLaptopRequest) ProtoMessage() {}
method ProtoReflect (line 146) | func (x *SearchLaptopRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 159) | func (*SearchLaptopRequest) Descriptor() ([]byte, []int) {
method GetFilter (line 163) | func (x *SearchLaptopRequest) GetFilter() *Filter {
type SearchLaptopResponse (line 170) | type SearchLaptopResponse struct
method Reset (line 178) | func (x *SearchLaptopResponse) Reset() {
method String (line 187) | func (x *SearchLaptopResponse) String() string {
method ProtoMessage (line 191) | func (*SearchLaptopResponse) ProtoMessage() {}
method ProtoReflect (line 193) | func (x *SearchLaptopResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 206) | func (*SearchLaptopResponse) Descriptor() ([]byte, []int) {
method GetLaptop (line 210) | func (x *SearchLaptopResponse) GetLaptop() *Laptop {
type UploadImageRequest (line 217) | type UploadImageRequest struct
method Reset (line 228) | func (x *UploadImageRequest) Reset() {
method String (line 237) | func (x *UploadImageRequest) String() string {
method ProtoMessage (line 241) | func (*UploadImageRequest) ProtoMessage() {}
method ProtoReflect (line 243) | func (x *UploadImageRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 256) | func (*UploadImageRequest) Descriptor() ([]byte, []int) {
method GetData (line 260) | func (m *UploadImageRequest) GetData() isUploadImageRequest_Data {
method GetInfo (line 267) | func (x *UploadImageRequest) GetInfo() *ImageInfo {
method GetChunkData (line 274) | func (x *UploadImageRequest) GetChunkData() []byte {
type isUploadImageRequest_Data (line 281) | type isUploadImageRequest_Data interface
type UploadImageRequest_Info (line 285) | type UploadImageRequest_Info struct
method isUploadImageRequest_Data (line 293) | func (*UploadImageRequest_Info) isUploadImageRequest_Data() {}
type UploadImageRequest_ChunkData (line 289) | type UploadImageRequest_ChunkData struct
method isUploadImageRequest_Data (line 295) | func (*UploadImageRequest_ChunkData) isUploadImageRequest_Data() {}
type ImageInfo (line 297) | type ImageInfo struct
method Reset (line 306) | func (x *ImageInfo) Reset() {
method String (line 315) | func (x *ImageInfo) String() string {
method ProtoMessage (line 319) | func (*ImageInfo) ProtoMessage() {}
method ProtoReflect (line 321) | func (x *ImageInfo) ProtoReflect() protoreflect.Message {
method Descriptor (line 334) | func (*ImageInfo) Descriptor() ([]byte, []int) {
method GetLaptopId (line 338) | func (x *ImageInfo) GetLaptopId() string {
method GetImageType (line 345) | func (x *ImageInfo) GetImageType() string {
type UploadImageResponse (line 352) | type UploadImageResponse struct
method Reset (line 361) | func (x *UploadImageResponse) Reset() {
method String (line 370) | func (x *UploadImageResponse) String() string {
method ProtoMessage (line 374) | func (*UploadImageResponse) ProtoMessage() {}
method ProtoReflect (line 376) | func (x *UploadImageResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 389) | func (*UploadImageResponse) Descriptor() ([]byte, []int) {
method GetId (line 393) | func (x *UploadImageResponse) GetId() string {
method GetSize (line 400) | func (x *UploadImageResponse) GetSize() uint32 {
type RateLaptopRequest (line 407) | type RateLaptopRequest struct
method Reset (line 416) | func (x *RateLaptopRequest) Reset() {
method String (line 425) | func (x *RateLaptopRequest) String() string {
method ProtoMessage (line 429) | func (*RateLaptopRequest) ProtoMessage() {}
method ProtoReflect (line 431) | func (x *RateLaptopRequest) ProtoReflect() protoreflect.Message {
method Descriptor (line 444) | func (*RateLaptopRequest) Descriptor() ([]byte, []int) {
method GetLaptopId (line 448) | func (x *RateLaptopRequest) GetLaptopId() string {
method GetScore (line 455) | func (x *RateLaptopRequest) GetScore() float64 {
type RateLaptopResponse (line 462) | type RateLaptopResponse struct
method Reset (line 472) | func (x *RateLaptopResponse) Reset() {
method String (line 481) | func (x *RateLaptopResponse) String() string {
method ProtoMessage (line 485) | func (*RateLaptopResponse) ProtoMessage() {}
method ProtoReflect (line 487) | func (x *RateLaptopResponse) ProtoReflect() protoreflect.Message {
method Descriptor (line 500) | func (*RateLaptopResponse) Descriptor() ([]byte, []int) {
method GetLaptopId (line 504) | func (x *RateLaptopResponse) GetLaptopId() string {
method GetRatedCount (line 511) | func (x *RateLaptopResponse) GetRatedCount() uint32 {
method GetAverageScore (line 518) | func (x *RateLaptopResponse) GetAverageScore() float64 {
function file_laptop_service_proto_rawDescGZIP (line 623) | func file_laptop_service_proto_rawDescGZIP() []byte {
function init (line 664) | func init() { file_laptop_service_proto_init() }
function file_laptop_service_proto_init (line 665) | func file_laptop_service_proto_init() {
FILE: pb/laptop_service.pb.gw.go
function request_LaptopService_CreateLaptop_0 (line 34) | func request_LaptopService_CreateLaptop_0(ctx context.Context, marshaler...
function local_request_LaptopService_CreateLaptop_0 (line 51) | func local_request_LaptopService_CreateLaptop_0(ctx context.Context, mar...
function request_LaptopService_SearchLaptop_0 (line 72) | func request_LaptopService_SearchLaptop_0(ctx context.Context, marshaler...
function request_LaptopService_UploadImage_0 (line 96) | func request_LaptopService_UploadImage_0(ctx context.Context, marshaler ...
function request_LaptopService_RateLaptop_0 (line 140) | func request_LaptopService_RateLaptop_0(ctx context.Context, marshaler r...
function RegisterLaptopServiceHandlerServer (line 196) | func RegisterLaptopServiceHandlerServer(ctx context.Context, mux *runtim...
function RegisterLaptopServiceHandlerFromEndpoint (line 247) | func RegisterLaptopServiceHandlerFromEndpoint(ctx context.Context, mux *...
function RegisterLaptopServiceHandler (line 272) | func RegisterLaptopServiceHandler(ctx context.Context, mux *runtime.Serv...
function RegisterLaptopServiceHandlerClient (line 281) | func RegisterLaptopServiceHandlerClient(ctx context.Context, mux *runtim...
FILE: pb/laptop_service_grpc.pb.go
constant _ (line 15) | _ = grpc.SupportPackageIsVersion7
type LaptopServiceClient (line 20) | type LaptopServiceClient interface
type laptopServiceClient (line 27) | type laptopServiceClient struct
method CreateLaptop (line 35) | func (c *laptopServiceClient) CreateLaptop(ctx context.Context, in *Cr...
method SearchLaptop (line 44) | func (c *laptopServiceClient) SearchLaptop(ctx context.Context, in *Se...
method UploadImage (line 76) | func (c *laptopServiceClient) UploadImage(ctx context.Context, opts .....
method RateLaptop (line 110) | func (c *laptopServiceClient) RateLaptop(ctx context.Context, opts ......
function NewLaptopServiceClient (line 31) | func NewLaptopServiceClient(cc grpc.ClientConnInterface) LaptopServiceCl...
type LaptopService_SearchLaptopClient (line 59) | type LaptopService_SearchLaptopClient interface
type laptopServiceSearchLaptopClient (line 64) | type laptopServiceSearchLaptopClient struct
method Recv (line 68) | func (x *laptopServiceSearchLaptopClient) Recv() (*SearchLaptopRespons...
type LaptopService_UploadImageClient (line 85) | type LaptopService_UploadImageClient interface
type laptopServiceUploadImageClient (line 91) | type laptopServiceUploadImageClient struct
method Send (line 95) | func (x *laptopServiceUploadImageClient) Send(m *UploadImageRequest) e...
method CloseAndRecv (line 99) | func (x *laptopServiceUploadImageClient) CloseAndRecv() (*UploadImageR...
type LaptopService_RateLaptopClient (line 119) | type LaptopService_RateLaptopClient interface
type laptopServiceRateLaptopClient (line 125) | type laptopServiceRateLaptopClient struct
method Send (line 129) | func (x *laptopServiceRateLaptopClient) Send(m *RateLaptopRequest) err...
method Recv (line 133) | func (x *laptopServiceRateLaptopClient) Recv() (*RateLaptopResponse, e...
type LaptopServiceServer (line 144) | type LaptopServiceServer interface
type UnimplementedLaptopServiceServer (line 153) | type UnimplementedLaptopServiceServer struct
method CreateLaptop (line 156) | func (UnimplementedLaptopServiceServer) CreateLaptop(context.Context, ...
method SearchLaptop (line 159) | func (UnimplementedLaptopServiceServer) SearchLaptop(*SearchLaptopRequ...
method UploadImage (line 162) | func (UnimplementedLaptopServiceServer) UploadImage(LaptopService_Uplo...
method RateLaptop (line 165) | func (UnimplementedLaptopServiceServer) RateLaptop(LaptopService_RateL...
method mustEmbedUnimplementedLaptopServiceServer (line 168) | func (UnimplementedLaptopServiceServer) mustEmbedUnimplementedLaptopSe...
type UnsafeLaptopServiceServer (line 173) | type UnsafeLaptopServiceServer interface
function RegisterLaptopServiceServer (line 177) | func RegisterLaptopServiceServer(s grpc.ServiceRegistrar, srv LaptopServ...
function _LaptopService_CreateLaptop_Handler (line 181) | func _LaptopService_CreateLaptop_Handler(srv interface{}, ctx context.Co...
function _LaptopService_SearchLaptop_Handler (line 199) | func _LaptopService_SearchLaptop_Handler(srv interface{}, stream grpc.Se...
type LaptopService_SearchLaptopServer (line 207) | type LaptopService_SearchLaptopServer interface
type laptopServiceSearchLaptopServer (line 212) | type laptopServiceSearchLaptopServer struct
method Send (line 216) | func (x *laptopServiceSearchLaptopServer) Send(m *SearchLaptopResponse...
function _LaptopService_UploadImage_Handler (line 220) | func _LaptopService_UploadImage_Handler(srv interface{}, stream grpc.Ser...
type LaptopService_UploadImageServer (line 224) | type LaptopService_UploadImageServer interface
type laptopServiceUploadImageServer (line 230) | type laptopServiceUploadImageServer struct
method SendAndClose (line 234) | func (x *laptopServiceUploadImageServer) SendAndClose(m *UploadImageRe...
method Recv (line 238) | func (x *laptopServiceUploadImageServer) Recv() (*UploadImageRequest, ...
function _LaptopService_RateLaptop_Handler (line 246) | func _LaptopService_RateLaptop_Handler(srv interface{}, stream grpc.Serv...
type LaptopService_RateLaptopServer (line 250) | type LaptopService_RateLaptopServer interface
type laptopServiceRateLaptopServer (line 256) | type laptopServiceRateLaptopServer struct
method Send (line 260) | func (x *laptopServiceRateLaptopServer) Send(m *RateLaptopResponse) er...
method Recv (line 264) | func (x *laptopServiceRateLaptopServer) Recv() (*RateLaptopRequest, er...
FILE: pb/memory_message.pb.go
constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
constant _ (line 26) | _ = proto.ProtoPackageIsVersion4
type Memory_Unit (line 28) | type Memory_Unit
method Enum (line 62) | func (x Memory_Unit) Enum() *Memory_Unit {
method String (line 68) | func (x Memory_Unit) String() string {
method Descriptor (line 72) | func (Memory_Unit) Descriptor() protoreflect.EnumDescriptor {
method Type (line 76) | func (Memory_Unit) Type() protoreflect.EnumType {
method Number (line 80) | func (x Memory_Unit) Number() protoreflect.EnumNumber {
method EnumDescriptor (line 85) | func (Memory_Unit) EnumDescriptor() ([]byte, []int) {
constant Memory_UNKNOWN (line 31) | Memory_UNKNOWN Memory_Unit = 0
constant Memory_BIT (line 32) | Memory_BIT Memory_Unit = 1
constant Memory_BYTE (line 33) | Memory_BYTE Memory_Unit = 2
constant Memory_KILOBYTE (line 34) | Memory_KILOBYTE Memory_Unit = 3
constant Memory_MEGABYTE (line 35) | Memory_MEGABYTE Memory_Unit = 4
constant Memory_GIGABYTE (line 36) | Memory_GIGABYTE Memory_Unit = 5
constant Memory_TERABYTE (line 37) | Memory_TERABYTE Memory_Unit = 6
type Memory (line 89) | type Memory struct
method Reset (line 98) | func (x *Memory) Reset() {
method String (line 107) | func (x *Memory) String() string {
method ProtoMessage (line 111) | func (*Memory) ProtoMessage() {}
method ProtoReflect (line 113) | func (x *Memory) ProtoReflect() protoreflect.Message {
method Descriptor (line 126) | func (*Memory) Descriptor() ([]byte, []int) {
method GetValue (line 130) | func (x *Memory) GetValue() uint64 {
method GetUnit (line 137) | func (x *Memory) GetUnit() Memory_Unit {
function file_memory_message_proto_rawDescGZIP (line 172) | func file_memory_message_proto_rawDescGZIP() []byte {
function init (line 194) | func init() { file_memory_message_proto_init() }
function file_memory_message_proto_init (line 195) | func file_memory_message_proto_init() {
FILE: pb/processor_message.pb.go
constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
constant _ (line 26) | _ = proto.ProtoPackageIsVersion4
type CPU (line 28) | type CPU struct
method Reset (line 41) | func (x *CPU) Reset() {
method String (line 50) | func (x *CPU) String() string {
method ProtoMessage (line 54) | func (*CPU) ProtoMessage() {}
method ProtoReflect (line 56) | func (x *CPU) ProtoReflect() protoreflect.Message {
method Descriptor (line 69) | func (*CPU) Descriptor() ([]byte, []int) {
method GetBrand (line 73) | func (x *CPU) GetBrand() string {
method GetName (line 80) | func (x *CPU) GetName() string {
method GetNumberCores (line 87) | func (x *CPU) GetNumberCores() uint32 {
method GetNumberThreads (line 94) | func (x *CPU) GetNumberThreads() uint32 {
method GetMinGhz (line 101) | func (x *CPU) GetMinGhz() float64 {
method GetMaxGhz (line 108) | func (x *CPU) GetMaxGhz() float64 {
type GPU (line 115) | type GPU struct
method Reset (line 127) | func (x *GPU) Reset() {
method String (line 136) | func (x *GPU) String() string {
method ProtoMessage (line 140) | func (*GPU) ProtoMessage() {}
method ProtoReflect (line 142) | func (x *GPU) ProtoReflect() protoreflect.Message {
method Descriptor (line 155) | func (*GPU) Descriptor() ([]byte, []int) {
method GetBrand (line 159) | func (x *GPU) GetBrand() string {
method GetName (line 166) | func (x *GPU) GetName() string {
method GetMinGhz (line 173) | func (x *GPU) GetMinGhz() float64 {
method GetMaxGhz (line 180) | func (x *GPU) GetMaxGhz() float64 {
method GetMemory (line 187) | func (x *GPU) GetMemory() *Memory {
function file_processor_message_proto_rawDescGZIP (line 232) | func file_processor_message_proto_rawDescGZIP() []byte {
function init (line 254) | func init() { file_processor_message_proto_init() }
function file_processor_message_proto_init (line 255) | func file_processor_message_proto_init() {
FILE: pb/screen_message.pb.go
constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
constant _ (line 26) | _ = proto.ProtoPackageIsVersion4
type Screen_Panel (line 28) | type Screen_Panel
method Enum (line 50) | func (x Screen_Panel) Enum() *Screen_Panel {
method String (line 56) | func (x Screen_Panel) String() string {
method Descriptor (line 60) | func (Screen_Panel) Descriptor() protoreflect.EnumDescriptor {
method Type (line 64) | func (Screen_Panel) Type() protoreflect.EnumType {
method Number (line 68) | func (x Screen_Panel) Number() protoreflect.EnumNumber {
method EnumDescriptor (line 73) | func (Screen_Panel) EnumDescriptor() ([]byte, []int) {
constant Screen_UNKNOWN (line 31) | Screen_UNKNOWN Screen_Panel = 0
constant Screen_IPS (line 32) | Screen_IPS Screen_Panel = 1
constant Screen_OLED (line 33) | Screen_OLED Screen_Panel = 2
type Screen (line 77) | type Screen struct
method Reset (line 88) | func (x *Screen) Reset() {
method String (line 97) | func (x *Screen) String() string {
method ProtoMessage (line 101) | func (*Screen) ProtoMessage() {}
method ProtoReflect (line 103) | func (x *Screen) ProtoReflect() protoreflect.Message {
method Descriptor (line 116) | func (*Screen) Descriptor() ([]byte, []int) {
method GetSizeInch (line 120) | func (x *Screen) GetSizeInch() float32 {
method GetResolution (line 127) | func (x *Screen) GetResolution() *Screen_Resolution {
method GetPanel (line 134) | func (x *Screen) GetPanel() Screen_Panel {
method GetMultitouch (line 141) | func (x *Screen) GetMultitouch() bool {
type Screen_Resolution (line 148) | type Screen_Resolution struct
method Reset (line 157) | func (x *Screen_Resolution) Reset() {
method String (line 166) | func (x *Screen_Resolution) String() string {
method ProtoMessage (line 170) | func (*Screen_Resolution) ProtoMessage() {}
method ProtoReflect (line 172) | func (x *Screen_Resolution) ProtoReflect() protoreflect.Message {
method Descriptor (line 185) | func (*Screen_Resolution) Descriptor() ([]byte, []int) {
method GetWidth (line 189) | func (x *Screen_Resolution) GetWidth() uint32 {
method GetHeight (line 196) | func (x *Screen_Resolution) GetHeight() uint32 {
function file_screen_message_proto_rawDescGZIP (line 238) | func file_screen_message_proto_rawDescGZIP() []byte {
function init (line 262) | func init() { file_screen_message_proto_init() }
function file_screen_message_proto_init (line 263) | func file_screen_message_proto_init() {
FILE: pb/storage_message.pb.go
constant _ (line 19) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 21) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
constant _ (line 26) | _ = proto.ProtoPackageIsVersion4
type Storage_Driver (line 28) | type Storage_Driver
method Enum (line 50) | func (x Storage_Driver) Enum() *Storage_Driver {
method String (line 56) | func (x Storage_Driver) String() string {
method Descriptor (line 60) | func (Storage_Driver) Descriptor() protoreflect.EnumDescriptor {
method Type (line 64) | func (Storage_Driver) Type() protoreflect.EnumType {
method Number (line 68) | func (x Storage_Driver) Number() protoreflect.EnumNumber {
method EnumDescriptor (line 73) | func (Storage_Driver) EnumDescriptor() ([]byte, []int) {
constant Storage_UNKNOWN (line 31) | Storage_UNKNOWN Storage_Driver = 0
constant Storage_HDD (line 32) | Storage_HDD Storage_Driver = 1
constant Storage_SSD (line 33) | Storage_SSD Storage_Driver = 2
type Storage (line 77) | type Storage struct
method Reset (line 86) | func (x *Storage) Reset() {
method String (line 95) | func (x *Storage) String() string {
method ProtoMessage (line 99) | func (*Storage) ProtoMessage() {}
method ProtoReflect (line 101) | func (x *Storage) ProtoReflect() protoreflect.Message {
method Descriptor (line 114) | func (*Storage) Descriptor() ([]byte, []int) {
method GetDriver (line 118) | func (x *Storage) GetDriver() Storage_Driver {
method GetMemory (line 125) | func (x *Storage) GetMemory() *Memory {
function file_storage_message_proto_rawDescGZIP (line 160) | func file_storage_message_proto_rawDescGZIP() []byte {
function init (line 184) | func init() { file_storage_message_proto_init() }
function file_storage_message_proto_init (line 185) | func file_storage_message_proto_init() {
FILE: sample/laptop.go
function NewKeyboard (line 9) | func NewKeyboard() *pb.Keyboard {
function NewCPU (line 19) | func NewCPU() *pb.CPU {
function NewGPU (line 42) | func NewGPU() *pb.GPU {
function NewRAM (line 65) | func NewRAM() *pb.Memory {
function NewSSD (line 77) | func NewSSD() *pb.Storage {
function NewHDD (line 92) | func NewHDD() *pb.Storage {
function NewScreen (line 107) | func NewScreen() *pb.Screen {
function NewLaptop (line 119) | func NewLaptop() *pb.Laptop {
function RandomLaptopScore (line 145) | func RandomLaptopScore() float64 {
FILE: sample/random.go
function init (line 11) | func init() {
function randomStringFromSet (line 15) | func randomStringFromSet(a ...string) string {
function randomBool (line 23) | func randomBool() bool {
function randomInt (line 27) | func randomInt(min, max int) int {
function randomFloat64 (line 31) | func randomFloat64(min, max float64) float64 {
function randomFloat32 (line 35) | func randomFloat32(min, max float32) float32 {
function randomID (line 39) | func randomID() string {
function randomKeyboardLayout (line 43) | func randomKeyboardLayout() pb.Keyboard_Layout {
function randomScreenResolution (line 54) | func randomScreenResolution() *pb.Screen_Resolution {
function randomScreenPanel (line 65) | func randomScreenPanel() pb.Screen_Panel {
function randomCPUBrand (line 72) | func randomCPUBrand() string {
function randomCPUName (line 76) | func randomCPUName(brand string) string {
function randomGPUBrand (line 94) | func randomGPUBrand() string {
function randomGPUName (line 98) | func randomGPUName(brand string) string {
function randomLaptopBrand (line 116) | func randomLaptopBrand() string {
function randomLaptopName (line 120) | func randomLaptopName(brand string) string {
FILE: serializer/file.go
function WriteProtobufToJSONFile (line 11) | func WriteProtobufToJSONFile(message proto.Message, filename string) err...
function WriteProtobufToBinaryFile (line 26) | func WriteProtobufToBinaryFile(message proto.Message, filename string) e...
function ReadProtobufFromBinaryFile (line 41) | func ReadProtobufFromBinaryFile(filename string, message proto.Message) ...
FILE: serializer/file_test.go
function TestFileSerializer (line 13) | func TestFileSerializer(t *testing.T) {
FILE: serializer/json.go
function ProtobufToJSON (line 9) | func ProtobufToJSON(message proto.Message) (string, error) {
function JSONToProtobufMessage (line 21) | func JSONToProtobufMessage(data string, message proto.Message) error {
FILE: service/auth_interceptor.go
type AuthInterceptor (line 14) | type AuthInterceptor struct
method Unary (line 25) | func (interceptor *AuthInterceptor) Unary() grpc.UnaryServerInterceptor {
method Stream (line 44) | func (interceptor *AuthInterceptor) Stream() grpc.StreamServerIntercep...
method authorize (line 62) | func (interceptor *AuthInterceptor) authorize(ctx context.Context, met...
function NewAuthInterceptor (line 20) | func NewAuthInterceptor(jwtManager *JWTManager, accessibleRoles map[stri...
FILE: service/auth_server.go
type AuthServer (line 12) | type AuthServer struct
method Login (line 24) | func (server *AuthServer) Login(ctx context.Context, req *pb.LoginRequ...
function NewAuthServer (line 19) | func NewAuthServer(userStore UserStore, jwtManager *JWTManager) pb.AuthS...
FILE: service/image_store.go
type ImageStore (line 13) | type ImageStore interface
type DiskImageStore (line 19) | type DiskImageStore struct
method Save (line 41) | func (store *DiskImageStore) Save(
type ImageInfo (line 26) | type ImageInfo struct
function NewDiskImageStore (line 33) | func NewDiskImageStore(imageFolder string) *DiskImageStore {
FILE: service/jwt_manager.go
type JWTManager (line 11) | type JWTManager struct
method Generate (line 29) | func (manager *JWTManager) Generate(user *User) (string, error) {
method Verify (line 43) | func (manager *JWTManager) Verify(accessToken string) (*UserClaims, er...
type UserClaims (line 17) | type UserClaims struct
function NewJWTManager (line 24) | func NewJWTManager(secretKey string, tokenDuration time.Duration) *JWTMa...
FILE: service/laptop_client_test.go
function TestClientCreateLaptop (line 21) | func TestClientCreateLaptop(t *testing.T) {
function TestClientSearchLaptop (line 48) | func TestClientSearchLaptop(t *testing.T) {
function TestClientUploadImage (line 116) | func TestClientUploadImage(t *testing.T) {
function TestClientRateLaptop (line 185) | func TestClientRateLaptop(t *testing.T) {
function startTestLaptopServer (line 232) | func startTestLaptopServer(t *testing.T, laptopStore service.LaptopStore...
function newTestLaptopClient (line 246) | func newTestLaptopClient(t *testing.T, serverAddress string) pb.LaptopSe...
function requireSameLaptop (line 252) | func requireSameLaptop(t *testing.T, laptop1 *pb.Laptop, laptop2 *pb.Lap...
FILE: service/laptop_server.go
constant maxImageSize (line 16) | maxImageSize = 1 << 20
type LaptopServer (line 19) | type LaptopServer struct
method CreateLaptop (line 36) | func (server *LaptopServer) CreateLaptop(
method SearchLaptop (line 84) | func (server *LaptopServer) SearchLaptop(
method UploadImage (line 114) | func (server *LaptopServer) UploadImage(stream pb.LaptopService_Upload...
method RateLaptop (line 192) | func (server *LaptopServer) RateLaptop(stream pb.LaptopService_RateLap...
function NewLaptopServer (line 27) | func NewLaptopServer(laptopStore LaptopStore, imageStore ImageStore, rat...
function contextError (line 241) | func contextError(ctx context.Context) error {
function logError (line 252) | func logError(err error) error {
FILE: service/laptop_server_test.go
function TestServerCreateLaptop (line 15) | func TestServerCreateLaptop(t *testing.T) {
FILE: service/laptop_store.go
type LaptopStore (line 18) | type LaptopStore interface
type InMemoryLaptopStore (line 28) | type InMemoryLaptopStore struct
method Save (line 41) | func (store *InMemoryLaptopStore) Save(laptop *pb.Laptop) error {
method Find (line 59) | func (store *InMemoryLaptopStore) Find(id string) (*pb.Laptop, error) {
method Search (line 72) | func (store *InMemoryLaptopStore) Search(
function NewInMemoryLaptopStore (line 34) | func NewInMemoryLaptopStore() *InMemoryLaptopStore {
function isQualified (line 105) | func isQualified(filter *pb.Filter, laptop *pb.Laptop) bool {
function toBit (line 125) | func toBit(memory *pb.Memory) uint64 {
function deepCopy (line 146) | func deepCopy(laptop *pb.Laptop) (*pb.Laptop, error) {
FILE: service/rating_store.go
type RatingStore (line 6) | type RatingStore interface
type Rating (line 12) | type Rating struct
type InMemoryRatingStore (line 18) | type InMemoryRatingStore struct
method Add (line 31) | func (store *InMemoryRatingStore) Add(laptopID string, score float64) ...
function NewInMemoryRatingStore (line 24) | func NewInMemoryRatingStore() *InMemoryRatingStore {
FILE: service/user.go
type User (line 10) | type User struct
method IsCorrectPassword (line 33) | func (user *User) IsCorrectPassword(password string) bool {
method Clone (line 39) | func (user *User) Clone() *User {
function NewUser (line 17) | func NewUser(username string, password string, role string) (*User, erro...
FILE: service/user_store.go
type UserStore (line 6) | type UserStore interface
type InMemoryUserStore (line 14) | type InMemoryUserStore struct
method Save (line 27) | func (store *InMemoryUserStore) Save(user *User) error {
method Find (line 40) | func (store *InMemoryUserStore) Find(username string) (*User, error) {
function NewInMemoryUserStore (line 20) | func NewInMemoryUserStore() *InMemoryUserStore {
Condensed preview — 78 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (342K chars).
[
{
"path": ".github/workflows/ci.yml",
"chars": 401,
"preview": "name: ci-test\n\non:\n push:\n branches: [ master ]\n pull_request:\n branches: [ master ]\n\njobs:\n\n test:\n name: T"
},
{
"path": "Makefile",
"chars": 790,
"preview": "clean:\n\trm pb/*\n\trm swagger/*\n\ngen:\n\tprotoc --proto_path=proto proto/*.proto --go_out=:pb --go-grpc_out=:pb --grpc-gate"
},
{
"path": "README.md",
"chars": 5462,
"preview": "# PC Book - Go\n\nThis repository contains the Golang codes for the hands-on section of [The complete gRPC course](http://"
},
{
"path": "cert/ca-cert.pem",
"chars": 2061,
"preview": "-----BEGIN CERTIFICATE-----\nMIIFxjCCA64CCQDY35xYDFXtHjANBgkqhkiG9w0BAQsFADCBpDELMAkGA1UEBhMC\nRlIxEjAQBgNVBAgMCU9jY2l0YW5"
},
{
"path": "cert/ca-cert.srl",
"chars": 17,
"preview": "B141E873FD7B8575\n"
},
{
"path": "cert/ca-key.pem",
"chars": 3272,
"preview": "-----BEGIN PRIVATE KEY-----\nMIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDJX7I3c8K/W2im\nEYi9VZm00jMZwh+5EBWFC5ddO91"
},
{
"path": "cert/client-cert.pem",
"chars": 2102,
"preview": "-----BEGIN CERTIFICATE-----\nMIIF4jCCA8qgAwIBAgIJALFB6HP9e4V1MA0GCSqGSIb3DQEBBQUAMIGkMQswCQYD\nVQQGEwJGUjESMBAGA1UECAwJT2N"
},
{
"path": "cert/client-ext.cnf",
"chars": 45,
"preview": "subjectAltName=DNS:*.pcclient.com,IP:0.0.0.0\n"
},
{
"path": "cert/client-key.pem",
"chars": 3272,
"preview": "-----BEGIN PRIVATE KEY-----\nMIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDdQfxUWvq0/wEB\n+rOTjeRhd0p8Mgr9QC588Fm+gFx"
},
{
"path": "cert/client-req.pem",
"chars": 1760,
"preview": "-----BEGIN CERTIFICATE REQUEST-----\nMIIE3DCCAsQCAQAwgZYxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZBbHNhY2UxEzAR\nBgNVBAcMClN0cmFzYm9"
},
{
"path": "cert/gen.sh",
"chars": 1507,
"preview": "rm *.pem\n\n# 1. Generate CA's private key and self-signed certificate\nopenssl req -x509 -newkey rsa:4096 -days 365 -nodes"
},
{
"path": "cert/server-cert.pem",
"chars": 2110,
"preview": "-----BEGIN CERTIFICATE-----\nMIIF6jCCA9KgAwIBAgIJALFB6HP9e4V0MA0GCSqGSIb3DQEBBQUAMIGkMQswCQYD\nVQQGEwJGUjESMBAGA1UECAwJT2N"
},
{
"path": "cert/server-ext.cnf",
"chars": 60,
"preview": "subjectAltName=DNS:*.pcbook.com,DNS:*.pcbook.org,IP:0.0.0.0\n"
},
{
"path": "cert/server-key.pem",
"chars": 3272,
"preview": "-----BEGIN PRIVATE KEY-----\nMIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDA6w7ev/e6XY7Z\nbWSRr2PtVguZdwE5jcuSij6Tg3p"
},
{
"path": "cert/server-req.pem",
"chars": 1756,
"preview": "-----BEGIN CERTIFICATE REQUEST-----\nMIIE2DCCAsACAQAwgZIxCzAJBgNVBAYTAkZSMRYwFAYDVQQIDA1JbGUgZGUgRnJh\nbmNlMQ4wDAYDVQQHDAV"
},
{
"path": "client/auth_client.go",
"chars": 875,
"preview": "package client\n\nimport (\n\t\"context\"\n\t\"time\"\n\n\t\"gitlab.com/techschool/pcbook/pb\"\n\t\"google.golang.org/grpc\"\n)\n\n// AuthClie"
},
{
"path": "client/auth_interceptor.go",
"chars": 2605,
"preview": "package client\n\nimport (\n\t\"context\"\n\t\"log\"\n\t\"time\"\n\n\t\"google.golang.org/grpc\"\n\t\"google.golang.org/grpc/metadata\"\n)\n\n// A"
},
{
"path": "client/laptop_client.go",
"chars": 4605,
"preview": "package client\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"time\"\n\n\t\"gitlab.com/techschool"
},
{
"path": "cmd/client/main.go",
"chars": 3691,
"preview": "package main\n\nimport (\n\t\"crypto/tls\"\n\t\"crypto/x509\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"strings\"\n\t\"time\"\n\n\t\"gitlab.com/"
},
{
"path": "cmd/server/main.go",
"chars": 5148,
"preview": "package main\n\nimport (\n\t\"context\"\n\t\"crypto/tls\"\n\t\"crypto/x509\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"net\"\n\t\"net/http\"\n\t\"t"
},
{
"path": "go.mod",
"chars": 479,
"preview": "module gitlab.com/techschool/pcbook\n\ngo 1.15\n\nrequire (\n\tgithub.com/dgrijalva/jwt-go v3.2.0+incompatible\n\tgithub.com/gol"
},
{
"path": "go.sum",
"chars": 42654,
"preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1"
},
{
"path": "img/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "nginx.conf",
"chars": 1204,
"preview": "worker_processes 1;\n\nerror_log /usr/local/var/log/nginx/error.log;\n\nevents {\n worker_connections 10;\n}\n\nhttp {\n "
},
{
"path": "pb/auth_service.pb.go",
"chars": 8111,
"preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.25.0\n// \tprotoc v3.14.0\n// sou"
},
{
"path": "pb/auth_service.pb.gw.go",
"chars": 6465,
"preview": "// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.\n// source: auth_service.proto\n\n/*\nPackage pb is a reverse pro"
},
{
"path": "pb/auth_service_grpc.pb.go",
"chars": 3529,
"preview": "// Code generated by protoc-gen-go-grpc. DO NOT EDIT.\n\npackage pb\n\nimport (\n\tcontext \"context\"\n\tgrpc \"google.golang.org/"
},
{
"path": "pb/filter_message.pb.go",
"chars": 6464,
"preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.25.0\n// \tprotoc v3.14.0\n// sou"
},
{
"path": "pb/keyboard_message.pb.go",
"chars": 7284,
"preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.25.0\n// \tprotoc v3.14.0\n// sou"
},
{
"path": "pb/laptop_message.pb.go",
"chars": 13129,
"preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.25.0\n// \tprotoc v3.14.0\n// sou"
},
{
"path": "pb/laptop_service.pb.go",
"chars": 28545,
"preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.25.0\n// \tprotoc v3.14.0\n// sou"
},
{
"path": "pb/laptop_service.pb.gw.go",
"chars": 14847,
"preview": "// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.\n// source: laptop_service.proto\n\n/*\nPackage pb is a reverse p"
},
{
"path": "pb/laptop_service_grpc.pb.go",
"chars": 9960,
"preview": "// Code generated by protoc-gen-go-grpc. DO NOT EDIT.\n\npackage pb\n\nimport (\n\tcontext \"context\"\n\tgrpc \"google.golang.org/"
},
{
"path": "pb/memory_message.pb.go",
"chars": 7390,
"preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.25.0\n// \tprotoc v3.14.0\n// sou"
},
{
"path": "pb/processor_message.pb.go",
"chars": 9908,
"preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.25.0\n// \tprotoc v3.14.0\n// sou"
},
{
"path": "pb/screen_message.pb.go",
"chars": 10165,
"preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.25.0\n// \tprotoc v3.14.0\n// sou"
},
{
"path": "pb/storage_message.pb.go",
"chars": 7454,
"preview": "// Code generated by protoc-gen-go. DO NOT EDIT.\n// versions:\n// \tprotoc-gen-go v1.25.0\n// \tprotoc v3.14.0\n// sou"
},
{
"path": "proto/auth_service.proto",
"chars": 500,
"preview": "syntax = \"proto3\";\n\npackage techschool.pcbook;\n\nimport \"google/api/annotations.proto\";\n\noption go_package = \".;pb\";\nopti"
},
{
"path": "proto/filter_message.proto",
"chars": 324,
"preview": "syntax = \"proto3\";\n\npackage techschool.pcbook;\n\noption go_package = \".;pb\";\noption java_package = \"com.gitlab.techschool"
},
{
"path": "proto/google/api/annotations.proto",
"chars": 1051,
"preview": "// Copyright (c) 2015, Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not "
},
{
"path": "proto/google/api/http.proto",
"chars": 12099,
"preview": "// Copyright 2018 Google LLC\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use th"
},
{
"path": "proto/google/api/httpbody.proto",
"chars": 2674,
"preview": "// Copyright 2018 Google LLC.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use t"
},
{
"path": "proto/google/rpc/code.proto",
"chars": 7056,
"preview": "// Copyright 2017 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use t"
},
{
"path": "proto/google/rpc/error_details.proto",
"chars": 7564,
"preview": "// Copyright 2017 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use t"
},
{
"path": "proto/google/rpc/status.proto",
"chars": 4047,
"preview": "// Copyright 2017 Google Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use t"
},
{
"path": "proto/keyboard_message.proto",
"chars": 317,
"preview": "syntax = \"proto3\";\n\npackage techschool.pcbook;\n\noption go_package = \".;pb\";\noption java_package = \"com.gitlab.techschool"
},
{
"path": "proto/laptop_message.proto",
"chars": 758,
"preview": "syntax = \"proto3\";\n\npackage techschool.pcbook;\n\noption go_package = \".;pb\";\noption java_package = \"com.gitlab.techschool"
},
{
"path": "proto/laptop_service.proto",
"chars": 1608,
"preview": "syntax = \"proto3\";\n\npackage techschool.pcbook;\n\noption go_package = \".;pb\";\noption java_package = \"com.gitlab.techschool"
},
{
"path": "proto/memory_message.proto",
"chars": 360,
"preview": "syntax = \"proto3\";\n\npackage techschool.pcbook;\n\noption go_package = \".;pb\";\noption java_package = \"com.gitlab.techschool"
},
{
"path": "proto/processor_message.proto",
"chars": 477,
"preview": "syntax = \"proto3\";\n\npackage techschool.pcbook;\n\noption go_package = \".;pb\";\noption java_package = \"com.gitlab.techschool"
},
{
"path": "proto/screen_message.proto",
"chars": 419,
"preview": "syntax = \"proto3\";\n\npackage techschool.pcbook;\n\noption go_package = \".;pb\";\noption java_package = \"com.gitlab.techschool"
},
{
"path": "proto/storage_message.proto",
"chars": 327,
"preview": "syntax = \"proto3\";\n\npackage techschool.pcbook;\n\noption go_package = \".;pb\";\noption java_package = \"com.gitlab.techschool"
},
{
"path": "sample/laptop.go",
"chars": 2832,
"preview": "package sample\n\nimport (\n\t\"github.com/golang/protobuf/ptypes\"\n\t\"gitlab.com/techschool/pcbook/pb\"\n)\n\n// NewKeyboard retur"
},
{
"path": "sample/random.go",
"chars": 2303,
"preview": "package sample\n\nimport (\n\t\"math/rand\"\n\t\"time\"\n\n\t\"github.com/google/uuid\"\n\t\"gitlab.com/techschool/pcbook/pb\"\n)\n\nfunc init"
},
{
"path": "serializer/file.go",
"chars": 1378,
"preview": "package serializer\n\nimport (\n\t\"fmt\"\n\t\"io/ioutil\"\n\n\t\"github.com/golang/protobuf/proto\"\n)\n\n// WriteProtobufToJSONFile writ"
},
{
"path": "serializer/file_test.go",
"chars": 744,
"preview": "package serializer_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/golang/protobuf/proto\"\n\t\"github.com/stretchr/testify/require\""
},
{
"path": "serializer/json.go",
"chars": 595,
"preview": "package serializer\n\nimport (\n\t\"github.com/golang/protobuf/jsonpb\"\n\t\"github.com/golang/protobuf/proto\"\n)\n\n// ProtobufToJS"
},
{
"path": "service/auth_interceptor.go",
"chars": 2391,
"preview": "package service\n\nimport (\n\t\"context\"\n\t\"log\"\n\n\t\"google.golang.org/grpc\"\n\t\"google.golang.org/grpc/codes\"\n\t\"google.golang.o"
},
{
"path": "service/auth_server.go",
"chars": 1140,
"preview": "package service\n\nimport (\n\t\"context\"\n\n\t\"gitlab.com/techschool/pcbook/pb\"\n\t\"google.golang.org/grpc/codes\"\n\t\"google.golang"
},
{
"path": "service/image_store.go",
"chars": 1601,
"preview": "package service\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"sync\"\n\n\t\"github.com/google/uuid\"\n)\n\n// ImageStore is an interface to s"
},
{
"path": "service/jwt_manager.go",
"chars": 1637,
"preview": "package service\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/dgrijalva/jwt-go\"\n)\n\n// JWTManager is a JSON web token manager\nty"
},
{
"path": "service/laptop_client_test.go",
"chars": 6276,
"preview": "package service_test\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/s"
},
{
"path": "service/laptop_server.go",
"chars": 6468,
"preview": "package service\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"io\"\n\t\"log\"\n\n\t\"github.com/google/uuid\"\n\t\"gitlab.com/techschool/"
},
{
"path": "service/laptop_server_test.go",
"chars": 1958,
"preview": "package service_test\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n\t\"gitlab.com/techschool/pcb"
},
{
"path": "service/laptop_store.go",
"chars": 3330,
"preview": "package service\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"sync\"\n\n\t\"github.com/jinzhu/copier\"\n\t\"gitlab.com/techschoo"
},
{
"path": "service/rating_store.go",
"chars": 1094,
"preview": "package service\n\nimport \"sync\"\n\n// RatingStore is an interface to store laptop ratings\ntype RatingStore interface {\n\t// "
},
{
"path": "service/user.go",
"chars": 1036,
"preview": "package service\n\nimport (\n\t\"fmt\"\n\n\t\"golang.org/x/crypto/bcrypt\"\n)\n\n// User contains user's information\ntype User struct "
},
{
"path": "service/user_store.go",
"chars": 1057,
"preview": "package service\n\nimport \"sync\"\n\n// UserStore is an interface to store users\ntype UserStore interface {\n\t// Save saves a "
},
{
"path": "swagger/auth_service.swagger.json",
"chars": 2027,
"preview": "{\n \"swagger\": \"2.0\",\n \"info\": {\n \"title\": \"auth_service.proto\",\n \"version\": \"version not set\"\n },\n \"tags\": [\n "
},
{
"path": "swagger/filter_message.swagger.json",
"chars": 825,
"preview": "{\n \"swagger\": \"2.0\",\n \"info\": {\n \"title\": \"filter_message.proto\",\n \"version\": \"version not set\"\n },\n \"consumes"
},
{
"path": "swagger/keyboard_message.swagger.json",
"chars": 827,
"preview": "{\n \"swagger\": \"2.0\",\n \"info\": {\n \"title\": \"keyboard_message.proto\",\n \"version\": \"version not set\"\n },\n \"consum"
},
{
"path": "swagger/laptop_message.swagger.json",
"chars": 825,
"preview": "{\n \"swagger\": \"2.0\",\n \"info\": {\n \"title\": \"laptop_message.proto\",\n \"version\": \"version not set\"\n },\n \"consumes"
},
{
"path": "swagger/laptop_service.swagger.json",
"chars": 12384,
"preview": "{\n \"swagger\": \"2.0\",\n \"info\": {\n \"title\": \"laptop_service.proto\",\n \"version\": \"version not set\"\n },\n \"tags\": ["
},
{
"path": "swagger/memory_message.swagger.json",
"chars": 825,
"preview": "{\n \"swagger\": \"2.0\",\n \"info\": {\n \"title\": \"memory_message.proto\",\n \"version\": \"version not set\"\n },\n \"consumes"
},
{
"path": "swagger/processor_message.swagger.json",
"chars": 828,
"preview": "{\n \"swagger\": \"2.0\",\n \"info\": {\n \"title\": \"processor_message.proto\",\n \"version\": \"version not set\"\n },\n \"consu"
},
{
"path": "swagger/screen_message.swagger.json",
"chars": 825,
"preview": "{\n \"swagger\": \"2.0\",\n \"info\": {\n \"title\": \"screen_message.proto\",\n \"version\": \"version not set\"\n },\n \"consumes"
},
{
"path": "swagger/storage_message.swagger.json",
"chars": 826,
"preview": "{\n \"swagger\": \"2.0\",\n \"info\": {\n \"title\": \"storage_message.proto\",\n \"version\": \"version not set\"\n },\n \"consume"
},
{
"path": "tmp/laptop.json",
"chars": 1172,
"preview": "{\n \"id\": \"22901c4c-2f34-43b6-8190-e3a57daa1a41\",\n \"brand\": \"Apple\",\n \"name\": \"Macbook Air\",\n \"cpu\": {\n \"brand\": \""
}
]
About this extraction
This page contains the full source code of the techschool/pcbook-go GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 78 files (311.7 KB), approximately 121.8k tokens, and a symbol index with 487 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.