Automatically create a scalajs file which will call REST apis defined in a Scala Play! server.
|
|
5 jaren geleden | |
|---|---|---|
| library | 5 jaren geleden | |
| plugin | 5 jaren geleden | |
| project | 5 jaren geleden | |
| .gitignore | 6 jaren geleden | |
| README.md | 5 jaren geleden | |
| build.sbt | 5 jaren geleden |
Rest is a programming paradigm built around using HTTP methods and status codes to communicate between a client and server.
A RESTful API uses HTTP methods to communicate actions. For example GET is a
request for information. PUT means insert or update information. And DELETE
removes information.
The path describes the data to operate on. For example /user/123/address might
refer to the address of a user with the id 123.
The body of a request contains the details about the request. For example the
body of the request PUT /user/123/address might contain a new address to
associate with the user.
The response body will often contain the result of the transaction or an error message.
RPC is a programming paradigm where a program calls a function which then runs on another system. From the client program's perspective, the API looks just like a normal function call. But the arguments to the function are actually sent to the server which the preforms the function and sends the result back to the client.
REST RPC is a plugin which creates an RPC interface over a RESTFUL one.
For example, say a program has an API PUT /user/:id/address which maps to the
function addUserAddress(id: Long, addr: Address): User. The client program
using REST RPC could then make this function call:
addUserAddress(123, myNewAddr)(). The RPC layer would then transform that
function call into this HTTP request:
PUT /user/123/address HTTP/1.1
Accept: application/json
{
"line1": "123 Home Ave.",
"line2": null,
"zip_code": 12345,
"city": "St. Sample",
"state": "CA"
}
And then transform the server's response into a strongly typed response. All without writing any HTTP manipulation.
Several reasons:
First, add the plugin to SBT by inserting this line into project/plugins.sbt:
addSbtPlugin("name.tflucke" % "sbt-rest-rpc" % "0.1.0")
Second, add the plugin to your project in build.sbt:
enablePlugins(RestRpc)
/* Or if you are using subprojects */
client.enablePlugins(RestRpc)
Finally, add the API file and parser as an input in build.sbt:
settings(
Compile / generateJsRoutes / fileInputs += (server / baseDirectory).value.toGlob / "conf" / "routes"
)
/* Or if you are using subprojects */
client.settings(
Compile / generateJsRoutes / fileInputs += (server / baseDirectory).value.toGlob / "conf" / "routes"
)
You can still use this plugin! You have two options which will work:
One is to create a routes file similar to the one play! framework uses. Even if it is not used by the server, REST RPC can still parse it to create the wrapper APIs.
Another option is to write an APIParser for whichever tool you use to create
your APIs. If you feel like you have something useful and robust, feel free to
share and we might add it to the plugin for other users.
This is not a problem. Add a config file containing a list of APIs for each of the servers or one file with a complete list. REST RPC will generate wrapper functions for each of the APIs for each of the servers so long as the servers do not have two functions with the same signature. (We recommend putting each server in a different package to guarantee that each function will be unique.)
Why does the client have to call the function twice?
Because we wanted the client to be able to access underlying HTTP properties if it became useful. For example, instead of calling the API, a program may want to acquire the URL like this:
println(addUserAddress(123, myNewAddr).url)
Outputs:
/user/123/address
Additionally, the second call allows the user to specify HTTP arguments separately from RPC arguments. For example:
addUserAddress(123, myNewAddr)(timeout = 5)
This clear separation between the RPC and HTTP helps both readability and reduce
collisions (After all, a user might want an RPC parameter named timeout).
Will this plugin support other frameworks besides the play! framework?
While this plugin in intended to be flexible, there are no immediate plans to support other frameworks at this time.
But we will still happily accept support from the community in this matter.