All Projects → easyCZ → Grpc Web Hacker News

easyCZ / Grpc Web Hacker News

Licence: mit
An example app implementing a Hacker News reader in React with gRPC-Web and Go backend

Programming Languages

typescript
32286 projects
golang
3204 projects

Projects that are alternatives of or similar to Grpc Web Hacker News

Cmakeprotosgrpc
gRPC + protobuf using CMake example
Stars: ✭ 137 (-53.4%)
Mutual labels:  grpc, example
Go Project Sample
Introduce the best practice experience of Go project with a complete project example.通过一个完整的项目示例介绍Go语言项目的最佳实践经验.
Stars: ✭ 344 (+17.01%)
Mutual labels:  grpc, example
go-grpc-bidirectional-streaming-example
gRPC bidirectional streaming example written in golang
Stars: ✭ 83 (-71.77%)
Mutual labels:  example, grpc
Ultimate Go
This repo contains my notes on working with Go and computer systems.
Stars: ✭ 1,530 (+420.41%)
Mutual labels:  grpc, example
Go Micro Boilerplate
The boilerplate of the GoLang application with a clear microservices architecture.
Stars: ✭ 147 (-50%)
Mutual labels:  grpc, example
Go Grpc Examples
This repo contains examples and implementations of different types of GRPC services and APIs using Golang.
Stars: ✭ 180 (-38.78%)
Mutual labels:  grpc, example
waypoint-plugin-examples
An example repository that demonstrates how to create and run an external Waypoint plugin
Stars: ✭ 16 (-94.56%)
Mutual labels:  example, grpc
Echox
Echo cookbook and website
Stars: ✭ 275 (-6.46%)
Mutual labels:  example
Yarpc Go
A message passing platform for Go
Stars: ✭ 285 (-3.06%)
Mutual labels:  grpc
Mirror
A tool for real-time, two-way sync for remote (e.g. desktop/laptop) development
Stars: ✭ 272 (-7.48%)
Mutual labels:  grpc
Api Docs
api.nasa.gov
Stars: ✭ 267 (-9.18%)
Mutual labels:  example
Cleancppproject
Clean C++ project for you to use. Features: Modern CMake, CPack, Doxygen, PlantUML, Catch Unit testing, static analysis
Stars: ✭ 276 (-6.12%)
Mutual labels:  example
Insomnia
The open-source, cross-platform API client for GraphQL, REST, and gRPC.
Stars: ✭ 18,969 (+6352.04%)
Mutual labels:  grpc
Turbo
A lightweight microservice tool, turn your grpc|thrift APIs into HTTP APIs!
Stars: ✭ 275 (-6.46%)
Mutual labels:  grpc
Joyrpc
high-performance, high-extensibility Java rpc framework.
Stars: ✭ 290 (-1.36%)
Mutual labels:  grpc
Gloo
The Feature-rich, Kubernetes-native, Next-Generation API Gateway Built on Envoy
Stars: ✭ 3,219 (+994.9%)
Mutual labels:  grpc
Surging
Surging is a micro-service engine that provides a lightweight, high-performance, modular RPC request pipeline. The service engine supports http, TCP, WS,Grpc, Thrift,Mqtt, UDP, and DNS protocols. It uses ZooKeeper and Consul as a registry, and integrates it. Hash, random, polling, Fair Polling as a load balancing algorithm, built-in service gove…
Stars: ✭ 3,088 (+950.34%)
Mutual labels:  grpc
Armeria
Your go-to microservice framework for any situation, from the creator of Netty et al. You can build any type of microservice leveraging your favorite technologies, including gRPC, Thrift, Kotlin, Retrofit, Reactive Streams, Spring Boot and Dropwizard.
Stars: ✭ 3,392 (+1053.74%)
Mutual labels:  grpc
Yoyogo
🦄🌈 YoyoGo is a simple, light and fast , dependency injection based micro-service framework written in Go. Support Nacos ,Consoul ,Etcd ,Eureka ,kubernetes.
Stars: ✭ 277 (-5.78%)
Mutual labels:  grpc
Vosk Server
WebSocket, gRPC and WebRTC speech recognition server based on Vosk and Kaldi libraries
Stars: ✭ 277 (-5.78%)
Mutual labels:  grpc

grpc-web-hacker-news

An example app implementing a Hacker News reader. This example aims to demonstrate usage of grpc-web(v0.5.0) with React. It additionally shows how to integrate with Redux.

Running

To start both the Go backend server and the frontend React application, run the following:

./start.sh

Screenshot

The backend server is running on http://localhost:8900 while the frontend will by default start on http://localhost:3000

Contributing

Contributions are welcome, please open an Issue or raise a PR.

Notable setup points

Disable TSLint for protobuf generated classes

Gernerated proto classes do not confirm to TS lint requirements, disable linting

{
    "linterOptions": {
        "exclude": [
            "src/proto/*"
        ]
    },
}

Configure protobuf compiler script

In this example, we're using a protoc.sh script to aid compilation

protoc \
    --go_out=plugins=grpc:./server \
    --plugin=protoc-gen-ts=./app/node_modules/.bin/protoc-gen-ts \
    --ts_out=service=true:./app/src \
    --js_out=import_style=commonjs,binary:./app/src \
    ./proto/hackernews.proto

Generated proto classes with Redux

Redux favors plain objects over object instances. This complicates usage of the generated proto classes, in this example class Story. In order to use the generated classes with redux, we must use the Story.AsObject type which is the plain object representation. For example our reducer should look like this:

export type StoryState = {
  readonly stories: { [storyId: number]: Story.AsObject },
  readonly error: Error | null,
  readonly loading: boolean,
  readonly selected: Story.AsObject | null,
};

export default function (state: StoryState = initialState, action: RootAction): StoryState {

  switch (action.type) {

    case ADD_STORY:
      const story: Story.AsObject = action.payload.toObject();
      const selected = state.selected !== null ? state.selected : story;
      if (story.id && story.id) {
        return {
          ...state,
          loading: false,
          stories: {...state.stories, [story.id]: story},
          selected,
        };
      }
      return state;

    default:
      return state;
  }

}

Note the usage of Story.AsObject rather than just Story

gRPC-Web Redux Middleware

An example redux middleware is included.

import { Action, Dispatch, Middleware, MiddlewareAPI } from 'redux';
import { Code, grpc, Metadata, Transport } from 'grpc-web-client';
import * as jspb from 'google-protobuf';

const GRPC_WEB_REQUEST = 'GRPC_WEB_REQUEST';
// const GRPC_WEB_INVOKE = 'GRPC_WEB_INVOKE';

// Descriptor of a grpc-web payload
// life-cycle methods mirror grpc-web but allow for an action to be dispatched when triggered
export type GrpcActionPayload<RequestType extends jspb.Message, ResponseType extends jspb.Message> = {
  // The method descriptor to use for a gRPC request, equivalent to grpc.invoke(methodDescriptor, ...)
  methodDescriptor: grpc.MethodDefinition<RequestType, ResponseType>,
  // The transport to use for grpc-web, automatically selected if empty
  transport?: Transport,
  // toggle debug messages
  debug?: boolean,
  // the URL of a host this request should go to
  host: string,
  // An instance of of the request message
  request: RequestType,
  // Additional metadata to attach to the request, the same as grpc-web
  metadata?: Metadata.ConstructorArg,
  // Called immediately before the request is started, useful for toggling a loading status
  onStart?: () => Action | void,
  // Called when response headers are received
  onHeaders?: (headers: Metadata) => Action | void,
  // Called on each incoming message
  onMessage?: (res: ResponseType) => Action | void,
  // Called at the end of a request, make sure to check the exit code
  onEnd: (code: Code, message: string, trailers: Metadata) => Action | void,
};

// Basic type for a gRPC Action
export type GrpcAction<RequestType extends jspb.Message, ResponseType extends jspb.Message> = {
  type: typeof GRPC_WEB_REQUEST,
  payload: GrpcActionPayload<RequestType, ResponseType>,
};

// Action creator, Use it to create a new grpc action
export function grpcRequest<RequestType extends jspb.Message, ResponseType extends jspb.Message>(
  payload: GrpcActionPayload<RequestType, ResponseType>
): GrpcAction<RequestType, ResponseType> {
  return {
    type: GRPC_WEB_REQUEST,
    payload,
  };
}

export function newGrpcMiddleware(): Middleware {
  return ({getState, dispatch}: MiddlewareAPI<{}>) => (next: Dispatch<{}>) => (action: any) => {
    // skip non-grpc actions
    if (!isGrpcWebUnaryAction(action)) {
      return next(action);
    }

    const payload = action.payload;

    if (payload.onStart) {
      payload.onStart();
    }

    grpc.invoke(payload.methodDescriptor, {
      debug: payload.debug,
      host: payload.host,
      request: payload.request,
      metadata: payload.metadata,
      transport: payload.transport,
      onHeaders: headers => {
        if (!payload.onHeaders) { return; }
        const actionToDispatch = payload.onHeaders(headers);
        return actionToDispatch && dispatch(actionToDispatch);
      },
      onMessage: res => {
        if (!payload.onMessage) { return; }
        const actionToDispatch = payload.onMessage(res);
        return actionToDispatch && dispatch(actionToDispatch);
      },
      onEnd: (code, msg, trailers) => {
        const actionToDispatch = payload.onEnd(code, msg, trailers);
        return actionToDispatch && dispatch(actionToDispatch);
      },
    });

    return next(action);
  };
}

function isGrpcWebUnaryAction(action: any): action is GrpcAction<jspb.Message, jspb.Message> {
  return action && action.type && action.type === GRPC_WEB_REQUEST && isGrpcWebPayload(action);
}

function isGrpcWebPayload(action: any): boolean {
  return action &&
    action.payload &&
    action.payload.methodDescriptor &&
    action.payload.request &&
    action.payload.onEnd &&
    action.payload.host;
}


Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].