Create a classic "RPC over HTTP" application for creating ads with pictures.
The application will encode the result of each operation in the body of the request.
For now, you only need to implement the server side. Use curl for testing the responses from the server.
http://localhost:3000/create-adThis is where clients should POST a json object to create a new ad. The JSON that's sent to the server should look like this:
{
"title": "Nice house for sale!",
"body": "Four rooms, huge bath."
}
To test the endpoint you can use the example ad.json file like this:
curl --data-binary @../ad.json http://localhost:3000/create-ad
The server should return a document like this:
{
"result": "ok",
"data": {
"id": "4fc494d10b6a9fcb09000001",
"body": "Four rooms, huge bath.",
"pictures": [],
"title": "Nice house for sale!"
},
}
The id field inside the data object is used later on when generating URLs.
Similar for any unknown error, result should be error:
{
"result": "error"
}
http://localhost:3000/ad?id=...Clients can GET this with an "id" query parameter. The server will respond with something like this:
{
"result": "ok",
"data": {
"title": "Nice house for sale!",
"body": "Four rooms, huge bath."
}
}
If the ad does not exist, result should be notFound:
{
"result": "notFound"
}
http://localhost:3000/add-picture?id=...There are some example pictures available under ../../pictures.
See the node cheat sheet on how to add pictures to a Mongo object.
ad.json{
"title": "Nice house for sale!",
"body": "Four rooms, huge bath."
}
The background and requirements are similar to the "RPC over HTTP" application, but now it's time to become a better and more "correct" HTTP component.
We will improve the application by moving generic application semantics one level down to the HTTP layer. We'll do this with proper use of status codes and headers.
We're expanding on the previous server, but this time we're also adding a client.
The application shall follow these general requirements:
Use application/json for all normal messages, and text/plain for error messages.
http://localhost:3000/create-adThis is where clients should POST a json object to create a new ad. The JSON that's sent to the server should look like this:
{
"title": "Nice house for sale!",
"body": "Four rooms, huge bath."
}
The server should return 200 Ok and a document like this:
{
"type": "ad",
"id": "4fc494d10b6a9fcb09000001",
"body": "Four rooms, huge bath.",
"pictures": [],
"title": "Nice house for sale!"
}
Try to send an invalid object (for example an empty document like /dev/null on unix or nul on windows) and make sure you're getting a proper 500 error code back.
http://localhost:3000/ad?id=...Clients can GET this with an "id" query parameter. The server will respond with something like this:
{
"type": "ad",
"id": "4fc494d10b6a9fcb09000001",
"body": "Four rooms, huge bath.",
"pictures": [],
"title": "Nice house for sale!"
}
Try to fetch an ad that doesn't exist and make sure you're getting a 404 error.
http://localhost:3000/add-pictureThere are some example pictures available under ../../pictures.
See the node cheat sheet on how to add pictures to a Mongo object.
The client shall first create the ad and then attach all the pictures to the ad.
Suggested command line API:
$ ./add-ad.js "Nice house for sale" "Four rooms, huge bath." car.jpg dinosaur.jpg
The client must assert the status codes and content types returned. Proper error handling is not important now so just throw an exception on any failure.
If the server returns an unexpected result or unprocessable content, do not crash but rather try to show the error message to the user. If the server returns text/plain, the user can be shown the text directly.
Last-Modified header to the responsesCreate a client that displays an ad.
Suggested command line API:
$ ./view-ad.js <id>
Fetching ad ...
Last-Modified: <time>
Title: <title>
Body: <body>
Improve the client and store the ad as ad-<id>.js. If executed twice it should do a conditional GET.
ad.json{
"title": "Nice house for sale!",
"body": "Four rooms, huge bath."
}
In this exercise it's time to move from application/json to use Ads'r'us' own media type. We will also remove all URL generation from the clients. The server will decide which interactions that are allowed.
Implement the API described in Ads'r'us API. Continue with the implementation you completed in the previous exercise.
Replace the usage of application/json with application/vnd.ad+json and application/vnd.ad-list+json. Update the add-ad.js client to start from the "ad list" URL and find the add-ad URL from the list document. In the end, the client should not hard code or generate any URLs.
Work with another person/group and try your client against the other groups server. Add extra fields and headers to the responses to try to get the other client to fail. Make sure that you stay within the specification when adding fields and headers. It is also possible to change the URL that's served to the client.
ad.jsonwoot
Now we're moving from a highly specific media type to encode the same objects by using an existing media type.
Update the server and client to use the new variant of the API.
This document is an example on how one can document an API by using the REST principles. This version of the API use a domain specific media type with JSON serialization.
This document describes an architecture for how agents should interact with Ads'r'us. Interactions with Ads'r'us follow the general architecture and constraints described in the REST dissertation and add some domain specific constraints.
We only implement a HTTP interface to our resources which come with its own set of constraints. As the world progresses, new specifications, updates and enhancements arrive and we try to stay as much as possible in line. However, we will always remain backwards compatible with our own published specifications.
Make sure to check back regularly to get the latest version of this specification!
These are general rules and principles used. They apply as long as a specific interaction/resource does not specify something else.
All resources should return an Allow header if the method is not allowed/supported.
It is expected that the domain and objects that the resources describe evolve over time and thus the media types will need evolve over time too. Clients must silently ignore unknown fieds and should not expect optional fields to be present.
When a new resource is created, the server MUST return the status code 201 and a Location header pointing to the newly created resource.
Many resources will include URIs to other resources and operations available for the client. The resources will include all links, even if the client may not be authorized to use them.
It is assumed that clients are pre-programmed with a link to an ad list when starting to interact with us.
application/vnd.ad+json{
"title": "Nice house for sale!",
"body": "Four rooms, huge bath.",
"pictures": [
URI, ...
]
"self": URI,
"add-picture": URI,
"publish": URI,
...
}
Fields:
title: the title and body of the ad. Available: summarybody: the title and body of the ad.self: the canonical URI for this ad. Can be used to send a link to other agents or when editing the ad.pictures: A JSON list of URLs that point to image files.add-picture: Send pictures here to add them to an ad.When updating the ad, only these fields needs to be sent:
titlebodyThere is no described way to update only a subset of the fields in an ad.
application/vnd.ad-list+json{
"count": 10,
"add-ad": URI,
"ads": [
{
// See specification for application/vnd.ad+json
}
],
"next-page": URI,
"prev-page": URI,
...
}
To insert a new ad into the list, send the data to the add-ad URI.
This document is an example on how one can document an API by using the REST principles. This version of the API uses the generic application/vnd.collection+json format instead of a specific media type.
This document describes an architecture for how agents should interact with Ads'r'us. Interactions with Ads'r'us follow the general architecture and constraints described in the REST dissertation and add some domain specific constraints.
We only implement a HTTP interface to our resources which come with its own set of constraints. Most of our data resources (non-binary) uses the existing application/vnd.collection+json media type, commonly known as "Collection+JSON":
Collection+JSON is a JSON-based read/write hypermedia-type designed to support management and querying of simple collections. It is similar to the The Atom Syndication Format (RFC4287) and the The Atom Publishing Protocol (RFC5023) . However, Collection+JSON defines both the format and the semantics in a single media type. It also includes support for Query Templates and expanded write support through the use of a Write Template.
As the world progresses, new specifications, updates and enhancements arrive and we try to stay as much as possible in line. However, we will always remain backwards compatible with our own published specifications.
Make sure to check back regularly to get the latest version of this specification!
These are general rules and principles used. They apply as long as a specific interaction/resource does not specify something else.
It is expected that the domain and objects that the resources describe evolve over time and thus new fields and link relations might be introduced later on. Clients must silently ignore unknown fieds and should not expect optional fields to be present.
It is assumed that clients are pre-programmed with a link to an ad list when starting to interact with us.
When serializing an ad inside a Collection+JSON, these fields are available:
title: The one-line title of the ad. MUST be present.body: The body part of the ad. MAY span multiple lines. MUST be present.lastModified: The timestamp of the ad. MUST use Atom's date format. See 3.3: Date Constructs. SHOULD be present when served from a server. MAY be present when a client sends one to the server.add-picture: Send pictures here to add them to an ad.In addition to the link relations specified by Collection+JSON, we use the picture relation to reference pictures that are related to the current resource.
{ "collection" :
{
"version": "1.0",
"href": "http://localhost:3000/ads",
"links": [
{"rel": "self", "href": "http://localhost:3000/ads"}
{"rel": "collection", "href": "http://localhost:3000/ads"}
{"rel": "feed", "href": "http://localhost:3000/ads.atom"}
],
"items": [
{
"href" : "...",
"data" : [
{"name" : "title", "value" : "Nice house for sale!", "prompt" : "Title"},
{"name" : "body", "value" : "Four rooms, huge bath.", "prompt" : "Ad Body"}
],
"links" : [
{"rel" : "add-picture", "href" : "..."}
{"rel" : "picture", "href" : "...", "render" : "image"}
{"rel" : "picture", "href" : "...", "render" : "image"}
]
},
...
]
}
}
As Collection+JSON does not have a way to send a single item only the context of the request specifies if the list will include one or more items.