DEV Community 👩‍💻👨‍💻

ankit-brijwasi
ankit-brijwasi

Posted on

Connect FastAPI & Golang services using gRPC

Hello Devs! Recently I started learning Protocol buffers & gRPC, and gotta tell you, this tech is amazing!

THIS POST REQUIRES A PRIOR KNOWLEDGE OF GRPC, GOLANG, AND PYTHON

Follow along with this post to get a hands-on demo on how to establish communication between different microservices that are running on different codebases using gRPC.

Find the code for this post here.

Directory Structure

fastapi-and-golang-grpc-demo
|-fastapi
    |-app
    |-env
    |-requirements.txt
|-protobufs
    |-auth.proto
|-main.go
|-Readme.md
|-go.mod
Enter fullscreen mode Exit fullscreen mode

Create the auth protobuf file

Open the auth.proto file on your favourite code editor, and add the following code to it

syntax = "proto3";
package auth;
option go_package = "auth.utils/auth";


message AuthenticationRequest {
    string token = 1;
}

message AuthenticationResponse {
    int64 user_id       = 1;
    bool  token_valid   = 2;
}

service Auth {
    rpc Authenticate (AuthenticationRequest) returns (AuthenticationResponse);
}
Enter fullscreen mode Exit fullscreen mode

Read more about protocol buffers here.

Add the Go service

1. Initialize the go application with

$ go mod init auth-ms
Enter fullscreen mode Exit fullscreen mode

2. Generate the gRPC code

$ protoc --go_out=. --go-grpc_out=. protobufs/auth.proto
Enter fullscreen mode Exit fullscreen mode

3. Update the dependencies

$ go mod tidy
Enter fullscreen mode Exit fullscreen mode

4. Let's create our gRPC server for golang, add the following code in the main.go file

package main

import (
    "context"
    "flag"
    "fmt"
    "log"
    "net"

    pb "auth-ms/auth.utils/auth"

    "google.golang.org/grpc"
)

var (
    port = flag.Int("port", 50051, "port to run the server on")
)

type server struct {
    pb.UnimplementedAuthServer
}

// extend the rpc service created in auth.proto
func (s *server) Authenticate(ctx context.Context, req *pb.AuthenticationRequest) (*pb.AuthenticationResponse, error) {
        token := req.GetToken()
        log.Printf("Received: %v", token)

        // add some logic to verify token
        return &pb.AuthenticationResponse{UserId: 1, TokenValid: true}, nil
}

func main() {
    flag.Parse()
    lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))

    if err != nil {
        log.Fatalln("Unable to start the server on port", *port)
    }

    grpc_server := grpc.NewServer()
    pb.RegisterAuthServer(grpc_server, &server{})
    log.Println("Started server at", lis.Addr())

    if err := grpc_server.Serve(lis); err != nil {
        log.Fatalln("Failed to start server at", lis.Addr())
    }
}
Enter fullscreen mode Exit fullscreen mode

5. Start the gRPC server and keep it opened

$ go run main.go -port 8080
2022/11/06 16:26:39 Started server at [::]:8080
Enter fullscreen mode Exit fullscreen mode

Add the FastAPI Service

1. Install the dependencies

$  pip install fastapi uvicorn grpcio-tools~=1.30
Enter fullscreen mode Exit fullscreen mode

2. Generate the gRPC code

$ cd ./fastapi/app/
$ python -m grpc_tools.protoc -I ../protobufs --python_out=. --grpc_python_out=. ../protobufs/auth.proto
Enter fullscreen mode Exit fullscreen mode

3. Create the FastAPI server

from fastapi import FastAPI
import grpc

from compiled_pb.auth_pb2_grpc import AuthStub
from compiled_pb.auth_pb2 import AuthenticationRequest

app = FastAPI()


@app.get("/token/verify/")
def verify_token(token: str):
    # gRPC client for making RPC calls to the server
    channel = grpc.insecure_channel("localhost:8080")
    client = AuthStub(channel)
    request = AuthenticationRequest(token=token)
    response = client.Authenticate(request)

    data = {
        "user_id": response.user_id,
        "is_token_valid": response.token_valid
    }
    return data
Enter fullscreen mode Exit fullscreen mode

4. Start the FastAPI sever

uvicorn main:app --host 127.0.0.1 --port 8000 --reload
INFO:     Will watch for changes in these directories: ['/home/ankit/practice/golang_gRPC/fastapi/app']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [8652] using StatReload
INFO:     Started server process [8654]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
Enter fullscreen mode Exit fullscreen mode

Now, go to, http:127.0.0.1:8000/docs and hit the, /token/verify/ route.

FastAPI server

VOILÀ, As soon as you hit the api request, there will be an internal RPC call to the go gRPC server.

golang gRPC server

Happy Coding!😊😇

Top comments (0)

Dream Big


Use any Linode offering to create something unique or silly in the DEV x Linode Hackathon 2022 and win the Wacky Wildcard category.

→ Join the Hackathon <-