Automatically create a scalajs file which will call REST apis defined in a Scala Play! server.
|
|
2 anos atrás | |
|---|---|---|
| library | 4 anos atrás | |
| play | 2 anos atrás | |
| plugin | 4 anos atrás | |
| project | 2 anos atrás | |
| .gitignore | 5 anos atrás | |
| README.md | 4 anos atrás | |
| build.sbt | 2 anos atrás | |
| test.sh | 5 anos atrás |
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 value. All without writing any HTTP manipulation.
Several reasons:
First, add the plugin to SBT by inserting this line into project/plugins.sbt:
addSbtPlugin("com.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:
client.settings(
Compile / apiDefinitions += PlayEndpointFile(server)
)
Sample projects can be found in the plugin/src/sbt-test/ directory.
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.)
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).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
namespace collisions (After all, a user might want an RPC parameter named
timeout).
It also allows the client to call the same API multiple times without re-computing the URL. This is useful for APIs which have windowed results.
Finally, it allows the client interface to have a separate parameter for the API body. This is useful because it eliminates the possibility of collisions and allows the client code to call the same interface with multiple bodies.
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.
TODO
sbt test will run the unit tests for this project.
sbt scripted will run the integration tests for this project.
Be warned that this will open browser windows.
We recommend using ./test.sh instead.
./test.sh will run all the tests. If Xvfb is available, it will run the tests
in a virtual X11 session to prevent unnecessary disruption of workflow and allow
the script to run on a headless server.