-
Notifications
You must be signed in to change notification settings - Fork 102
Getting Started
The goal of the rest-shell
is to make it much easier to work with HATEOAS HTTP-based REST services by providing a command shell interface that keeps track of where you are in the HTTP resource hierarchy and allow you to specify URLs by short, relative paths, or by rel reference.
Releases can be downloaded from the GitHub rest-shell downloads page or built from source.
If you're using Mac OS X and Homebrew, you can install the rest-shell
using brew install
(NOTE: when the pull request is accepted...still waiting on that):
> brew install rest-shell
==> Downloading https://github.com/downloads/jbrisbin/rest-shell/rest-shell-1.1.2.RELEASE.tar.gz
######################################################################## 100.0%
/usr/local/Cellar/rest-shell/1.1.2.RELEASE: 28 files, 6.0M, built in 27 seconds
Using the rest-shell
to navigate your REST resources is very similar to traversing a directory structure in your system terminal. The rest-shell
always maintains a baseUri
that is considered the root to which all other path references are considered relative. If you have a REST service exposed at http://localhost:8080/api
, then you'd consider that your baseUri
.
But your base URI will change based on the context in which you are issuing requests. For example, if you have a REST resource exposed at /system/main
, then your rest-shell
interaction might look like this:
> rest-shell
___ ___ __ _____ __ _ _ _ _ __
| _ \ __/' _/_ _/' _/| || | / / | \ \
| v / _|`._`. | | `._`.| >< | / / / > >
|_|_\___|___/ |_| |___/|_||_| |_/_/ /_/
Welcome to the REST shell. For assistance hit TAB or type "help".
http://localhost:8080:> baseUri http://localhost:8080/api
Base URI set to 'http://localhost:8080/api'
http://localhost:8080/api:> get system/main
> GET http://localhost:8080/api/system/main
< 200 OK
< ... response from server
One of the central tenets of HATEOAS is discoverability via links. The rest-shell
understands links natively if they conform to the Spring HATEOAS pattern. You don't have to be using the Spring HATEOAS library for your server-side resources (though it's definitely encouraged that you do). If the JSON resource returned contains a property called links
which is an array of objects with a rel
and href
property, then the rest-shell
can "discover" these resources and provide you an easy way to refer to these URIs later.
For example, if I'm using the Spring Data REST project to export my JPA Entities as RESTful services, I'll receive a list of links to the repositories being exported if I request the root URL of the application. Assuming my WAR is deployed on the context path /data
, I can discover those resources by using the rest-shell
command discover
:
http://localhost:8080:> discover http://localhost:8080/data
rel href
=================================================================
address http://localhost:8080/data/address
family http://localhost:8080/data/family
customerTracker http://localhost:8080/data/customerTracker
customer http://localhost:8080/data/customer
people http://localhost:8080/data/people
profile http://localhost:8080/data/profile
http://localhost:8080/data:>
NOTE: Since the rest-shell
understands relative paths so well, we could have easily substituted discover data
here and got the same result.
This table is built up from JSON that looks like this:
{
"links" : [ {
"rel" : "address",
"href" : "http://localhost:8080/data/address"
}, {
"rel" : "family",
"href" : "http://localhost:8080/data/family"
}, {
"rel" : "customerTracker",
"href" : "http://localhost:8080/data/customerTracker"
}, {
"rel" : "customer",
"href" : "http://localhost:8080/data/customer"
}, {
"rel" : "people",
"href" : "http://localhost:8080/data/people"
}, {
"rel" : "profile",
"href" : "http://localhost:8080/data/profile"
} ],
"content" : [ ]
}
Once a resource has been "discovered", I can replace references to the absolute or relative URI with a reference to the rel. This includes tab completeion support. To test this, type the following in the rest-shell
:
http://localhost:8080/data:> follow --rel p<TAB>
people profile
http://localhost:8080/data:> follow --rel people
This saves a lot of typing because I don't have to continually type out (or copy and paste) the full URI to the resource I'm interested in.
The follow
command we used above just resets the baseUri
but doesn't query the REST server to find out what links are available from the current context like the discover
command does. If you want to know what resources are available at the present baseUri
, though, you use the list
command:
http://localhost:8080/data/people:> list
rel href
=========================================================
people.Person http://localhost:8080/data/people/1
people.Person http://localhost:8080/data/people/2
people.search http://localhost:8080/data/people/search
http://localhost:8080/data/people:>
You can also list
resources found at relative paths beneath the current baseUri
without altering the current baseUri
:
http://localhost:8080/data/people:> list search
rel href
================================================================================
people.id http://localhost:8080/data/people/search/id
people.names http://localhost:8080/data/people/search/name
people.count http://localhost:8080/data/people/search/count
people.created http://localhost:8080/data/people/search/created
people.nameStartsWith http://localhost:8080/data/people/search/nameStartsWith
http://localhost:8080/data/people:>
To GET
a resource, use the get
command. If you type help get
in the rest-shell
, you'll get a comprehensive list of the options available on this command. For example, to get the resource with the rel people.count
, type:
http://localhost:8080/data/people:> get --rel people.count
> GET http://localhost:8080/data/people/search/count
< 200 OK
< Content-Length: 40
< Content-Type: application/json
<
{
"links" : [ ],
"content" : [ 2 ]
}
http://localhost:8080/data/people:>
If you're get
ing a resource that requires query parameters, you don't include them yourself in the path by adding a question mark. There is some underlying munging of text that needs to happen first (mainly proper URL encoding). Instead, you set query parameters as a JSON fragment:
http://localhost:8080/data/people:> get --rel people.nameStartsWith --params "{name: 'John'}"
> GET http://localhost:8080/data/people/search/nameStartsWith?name=John
< 200 OK
< Content-Length: 643
< Content-Type: application/json
<
{
"links" : [ ],
"content" : [ {
... response
} ]
}
http://localhost:8080/data/people:>
If you expect to get a redirect via Location
header and you want to immediately follow that redirect, add the --follow true
option to the get
command.
If you want to pipe the output to a local file rather than dumping it into the console, then provide a file name on the --output
option:
http://localhost:8080/data/people:> get --rel people.count --output people_count.txt
>> people_count.txt
http://localhost:8080/data/people:> ! cat people_count.txt
command is:cat people_count.txt
> GET http://localhost:8080/data/people/search/count
< 200 OK
< Date: Mon, 22 Oct 2012 19:07:40 GMT
< Content-Length: 40
< Content-Type: application/json
< Server: Jetty(8.1.5.v20120716)
<
{
"links" : [ ],
"content" : [ 2 ]
}
http://localhost:8080/data/people:>
NOTE: The "bang", or exclamation mark, is the command inside the Spring shell that says "run this on the underlying terminal".
To send data to the server, either include a JSON fragment inline in the --data
option, provide an expression that will evaluate to an object to serialize (more on this on the page describing context variable and expression language support), or specify a file or directory of files from which to read the JSON to send to the server.
To send JSON data directly inline from the rest-shell
, simply include it as the string argument to the --data
option. Keep in mind, however, that there are some limitations in the shell parsing, so you need to use either single quotes for strings inside your JSON, or make sure they are properly backslashed (the former is much easier, though not technically "proper" JSON). To make it easier to read the JSON going out to the server, it's also possible to omit quotes around field names. You're probably used to doing this in Javascript, but it's not technically proper JSON. No matter! The rest-shell
is all about making your life easier, so the rest-shell
takes a very laissez-faire attitude toward the JSON you include on the command line.
http://localhost:8080/data/people:> post --data "{name: 'John Doe'}"
> POST http://localhost:8080/data/people/
< 201 CREATED
< Location: http://localhost:8080/data/people/3
< Content-Length: 0
< Content-Type: text/html
<
http://localhost:8080/data/people:>