How the user input values-text fields, in lora-app-server, post that value to golang at backend?

Hello, Everyone & @brocaar !

I am trying to look for the backend code (written in golang) which accepts or gets value from the LoRa-App-Server’s text fields (frontend: React.js) and later on inserts that data into the database (postgres & Redis).

For Example: As LoRa-App-Server is connected to LoRa Server over gRPC, when we create a Gateway on LoRa-App-Server, we have to fill this GatewayForm having GatewayDetails, like GatewayName, GatewayID…,etc.

My question is, that, after clicking on the ‘CREAT GATEWAY’ button, where does all of this data is ‘posted’ or ‘stored’ in Golang, such that Golang inserts all of this data, into the database??

It would be great if anybody can guide me to that file, where all the data is posted from React.js to Golang.

Thank You!

Handlers for the available API methods are located at /internal/api/external, so in this case you’d want to look at https://github.com/brocaar/lora-app-server/blob/master/internal/api/external/gateway.go#L36.

There you’ll see that -among other things- the gateway is created by calling the storage.CreateGateway function from the storage package, and calling the external gRPC method nsClient.CreateGateway, from the network server (i.e. loraserver).

The former is defined at https://github.com/brocaar/lora-app-server/blob/master/internal/storage/gateway.go#L95.

The latter at https://github.com/brocaar/loraserver/blob/master/internal/api/network_server.go#L796.

Hope that helps.

2 Likes

Hi, @iegomez! Thank you for taking the time to reply!

Correct me if I’m wrong, but as per my understanding you mean to say is, that ;

  1. we fetch the user-input value from the Lora-App-Server, through CreateGatewayRequest struct (https://github.com/brocaar/lora-app-server/blob/cf02d43439f0a5c863316e75d9bdd58a1652cb94/api/gateway.pb.go#L194 ),
  1. Then, it calls ns.CreateGatewayRequest (https://github.com/brocaar/lora-app-server/blob/cf02d43439f0a5c863316e75d9bdd58a1652cb94/internal/api/external/gateway.go#L61), copies mac[:] into Id.

  2. Then calls the storage.CreateGateway to store the value of mac into MAC:, in the database, (https://github.com/brocaar/lora-app-server/blob/cf02d43439f0a5c863316e75d9bdd58a1652cb94/internal/api/external/gateway.go#L99).

  3. After storing it, it calls the external gRPC method of loraserver, using nsClient.CreateGateway. (but for what?) (possibly for sending the copied Id from mac[:] to loraserver? : To store it in gw.GatewayID[:](https://github.com/brocaar/loraserver/blob/253bb9e6d96fac97d07cdda6912c1d178d99cc0d/internal/api/network_server.go#L814)).

Did I get all these points right?

Also, @iegomez, I know for a fact that Lora-app-server posts and gets the data from the application(React.js) in protobuf format through gRPC API.

But what if I want to get and post data in JSON format over HTTP? Is it possible?

Don’t bother checking *pb.go files, those are autogenerated when you compile the protobuf services (i.e., when calling make api). Instead, check the proto definition and the actual implementation, e.g., /api/gateway.proto and the mentioned files.

Both lora-app-server and loraserver store gateway information, as the first needs to allow the user to manage them, while the second does all the LoRaWAN network related work and thus needs to be aware of gateways.

That’s not right. The frontend application communicates with lora-app-server through HTTP using the exposed REST API built by the grpc-gateway. In short, lora-app-server defines it’s API as gRPC services, but it also exposes a REST one by autogenerating HTTP endpoints from your proto definitions. That’s why services methods define an HTTP verb and an endpoint uri, e.g. a PUT request for a gateway update:

// Update updates the gateway matching the given mac address.
	rpc Update(UpdateGatewayRequest) returns (google.protobuf.Empty) {
		option (google.api.http) = {
			put: "/api/gateways/{gateway.id}"
			body: "*"
		};
	}

When calling make api, not only will the proto definitions get compiled to Go code for those services (/api/*.pb.go files), it’ll also call the grpc-gateway plugin to generate HTTP endpoints for those services too (/api/*.pb.gw.go files) and the swagger plugin to generate swagger definitions for your API (/api/swagger/*.swagger.json files).

The React app that’s shipped with lora-app-server imports the swagger-client package to make use of the swagger definitions to implement the clients, but if you open up your inspector at the browser you’ll see regular HTTP requests going to the server and you may try those in any HTTP client.

So yeah, that’s exactly what happens and you can do it yourself too.

1 Like

Thanks for your reply, @iegomez! This explanation cleared a lot of things for me.

However, One more question,in reference to this:

This point is clear that to support RESTful JSON API, HTTP endpoints are generated inside the .proto files.

But since the react-ui posts JSON data over HTTP, and then how does the grpc-gateway plugin of protoc convert this JSON data posted by HTTP endpoints into protobuf? So that the data in protobuf format can be posted over gRPC.

The autogenerated /api/*.pb.gw.go files do it (please check one of them for more details), basically by getting the json data from the *http.Request and decoding it to the correct proto request (depending on the method), calling the gRPC service method with this proto request and then forwarding back the response to the client by translating it back to json.

For details about registering services for either the gRPC or the HTTP APIs, check the /internal/api/external/external.go file from lora-app-server.

1 Like

Thank you @iegomez, your explanation helped me get better understanding of the code. I had one more doubt in my mind:
That React.js runs in localhost:8080, if we make our own Golang API to get the JSON encoded data, how can we get the data from the same port i.e. 8080, so that it doesn’t show the error : port:8080 already in use?

Sorry, I don’t think I understand your question. What do you mean with your own Go API to get the json encoded data? What data? From where? I thought you wanted to extend lora-app-server's API, not create a separate one.

1 Like

Sorry, I wasn’t clear with my question. Yes, I wanted to do that only. So aren’t the lora-app-server/api made on Golang? Can you guide me to some files which point to the API code, such as, for e.g., sending downlink to the device through the api?

Well, then this doesn’t make much sense:

You don’t want to run a separate API or service in that port, you want to modify lora-app-server's source, build it and then run it as usual. As mentioned in earlier posts, that usually means modifying your gRPC services definitions and implementations, which are located at /api/service-name.proto and /internal/api/external/service-name.go respectively. You don’t need to worry about the REST conversion, that’s taken care for you by the grpc-gateway plugin when you build the proto definitions.