Skip to content

Commit

Permalink
Merge pull request grpc-ecosystem#23 from Unix4ever/properly-encode-u…
Browse files Browse the repository at this point in the history
…int8array

Properly encode Uint8Array fields
  • Loading branch information
lyonlai authored Aug 5, 2021
2 parents 4a93113 + f6cb5af commit f3ef8ab
Show file tree
Hide file tree
Showing 9 changed files with 628 additions and 240 deletions.
113 changes: 111 additions & 2 deletions generator/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,119 @@ const fetchTmpl = `
* This file is a generated Typescript file for GRPC Gateway, DO NOT MODIFY
*/
/**
* base64 encoder and decoder
* Copied and adapted from https://github.com/protobufjs/protobuf.js/blob/master/lib/base64/index.js
*/
// Base64 encoding table
const b64 = new Array(64);
// Base64 decoding table
const s64 = new Array(123);
// 65..90, 97..122, 48..57, 43, 47
for (let i = 0; i < 64;)
s64[b64[i] = i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i - 59 | 43] = i++;
export function b64Encode(buffer: Uint8Array, start: number, end: number): string {
let parts: string[] = null;
const chunk = [];
let i = 0, // output index
j = 0, // goto index
t; // temporary
while (start < end) {
const b = buffer[start++];
switch (j) {
case 0:
chunk[i++] = b64[b >> 2];
t = (b & 3) << 4;
j = 1;
break;
case 1:
chunk[i++] = b64[t | b >> 4];
t = (b & 15) << 2;
j = 2;
break;
case 2:
chunk[i++] = b64[t | b >> 6];
chunk[i++] = b64[b & 63];
j = 0;
break;
}
if (i > 8191) {
(parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
i = 0;
}
}
if (j) {
chunk[i++] = b64[t];
chunk[i++] = 61;
if (j === 1)
chunk[i++] = 61;
}
if (parts) {
if (i)
parts.push(String.fromCharCode.apply(String, chunk.slice(0, i)));
return parts.join("");
}
return String.fromCharCode.apply(String, chunk.slice(0, i));
}
const invalidEncoding = "invalid encoding";
export function b64Decode(s: string): Uint8Array {
const buffer = [];
let offset = 0;
let j = 0, // goto index
t; // temporary
for (let i = 0; i < s.length;) {
let c = s.charCodeAt(i++);
if (c === 61 && j > 1)
break;
if ((c = s64[c]) === undefined)
throw Error(invalidEncoding);
switch (j) {
case 0:
t = c;
j = 1;
break;
case 1:
buffer[offset++] = t << 2 | (c & 48) >> 4;
t = c;
j = 2;
break;
case 2:
buffer[offset++] = (t & 15) << 4 | (c & 60) >> 2;
t = c;
j = 3;
break;
case 3:
buffer[offset++] = (t & 3) << 6 | c;
j = 0;
break;
}
}
if (j === 1)
throw Error(invalidEncoding);
return new Uint8Array(buffer);
}
function b64Test(s: string): boolean {
return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(s);
}
export interface InitReq extends RequestInit {
pathPrefix?: string
}
export function replacer(key: any, value: any): any {
if(value && value.constructor === Uint8Array) {
return b64Encode(value, 0, value.length);
}
return value;
}
export function fetchReq<I, O>(path: string, init?: InitReq): Promise<O> {
const {pathPrefix, ...req} = init || {}
Expand Down Expand Up @@ -399,9 +508,9 @@ func buildInitReq(method data.Method) string {
m := `method: "` + httpMethod + `"`
fields := []string{m}
if method.HTTPRequestBody == nil || *method.HTTPRequestBody == "*" {
fields = append(fields, "body: JSON.stringify(req)")
fields = append(fields, "body: JSON.stringify(req, fm.replacer)")
} else if *method.HTTPRequestBody != "" {
fields = append(fields, `body: JSON.stringify(req["`+*method.HTTPRequestBody+`"])`)
fields = append(fields, `body: JSON.stringify(req["`+*method.HTTPRequestBody+`"], fm.replacer)`)
}

return strings.Join(fields, ", ")
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ require (
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013
google.golang.org/grpc v1.33.1
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 // indirect
google.golang.org/protobuf v1.25.0
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1 h1:DGeFlSan2f+WEtCERJ4J9GJWk15TxUi8QGagfI87Xyc=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.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=
Expand Down
12 changes: 12 additions & 0 deletions integration_tests/integration_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { expect } from 'chai';
import camelCase from 'lodash.camelcase';
import { pathOr } from 'ramda';
import { CounterService } from "./service.pb";
import { b64Decode } from './fetch.pb';

function getFieldName(name: string) {
const useCamelCase = pathOr(false, ['__karma__', 'config', 'useProtoNames'], window) === false
Expand Down Expand Up @@ -36,6 +37,17 @@ describe("test grpc-gateway-ts communication", () => {
expect(response).to.deep.equal([2, 3, 4, 5, 6])
})

it('binary echo', async () => {
const message = "→ ping";

const resp:any = await CounterService.EchoBinary({
data: new TextEncoder().encode(message),
}, { pathPrefix: "http://localhost:8081" })

const bytes = b64Decode(resp["data"])
expect(new TextDecoder().decode(bytes)).to.equal(message)
})

it('http get check request', async () => {
const result = await CounterService.HTTPGet({ [getFieldName('num_to_increase')]: 10 }, { pathPrefix: "http://localhost:8081" })
expect(result.result).to.equal(11)
Expand Down
2 changes: 1 addition & 1 deletion integration_tests/msg.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion integration_tests/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import (
"google.golang.org/protobuf/types/known/emptypb"
)

type RealCounterService struct{}
type RealCounterService struct {
UnimplementedCounterServiceServer
}

func (r *RealCounterService) ExternalMessage(ctx context.Context, request *ExternalRequest) (*ExternalResponse, error) {
return &ExternalResponse{
Expand All @@ -27,6 +29,12 @@ func (r *RealCounterService) FailingIncrement(c context.Context, req *UnaryReque
return nil, status.Errorf(codes.Unavailable, "this increment does not work")
}

func (r *RealCounterService) EchoBinary(c context.Context, req *BinaryRequest) (*BinaryResponse, error) {
return &BinaryResponse{
Data: req.Data,
}, nil
}

func (r *RealCounterService) StreamingIncrements(req *StreamingRequest, service CounterService_StreamingIncrementsServer) error {
times := 5
counter := req.Counter
Expand Down
Loading

0 comments on commit f3ef8ab

Please sign in to comment.