-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #52 from ba-st/docs
Update documentation
- Loading branch information
Showing
11 changed files
with
428 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Superluminal Documentation | ||
|
||
Superluminal provides building blocks for creating HTTP requests and API | ||
clients, including: | ||
|
||
- Entity tags handling | ||
- Caching | ||
- Service Discovery | ||
|
||
To learn about the project, [install it](how-to/how-to-load-in-pharo.md) and | ||
lookup for details in the reference docs: | ||
|
||
- [HTTP Requests](reference/HTTP-Requests.md) | ||
- [API Clients](reference/API-Client.md) | ||
- [Service Discovery](reference/Service-Discovery.md) | ||
|
||
--- | ||
|
||
To use the project as a dependency of your project, take a look at: | ||
|
||
- [How to use Superluminal as a dependency](how-to/how-to-use-as-dependency-in-pharo.md) | ||
- [Baseline groups reference](reference/Baseline-groups.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# How to load Superluminal in a Pharo image | ||
|
||
## Using Metacello | ||
|
||
1. Download a [Pharo VM and image](https://pharo.org/download) | ||
2. Open your Pharo image | ||
3. Open a Playground | ||
4. Evaluate: | ||
|
||
```smalltalk | ||
Metacello new | ||
baseline: 'Superluminal'; | ||
repository: 'github://ba-st/Superluminal:release-candidate'; | ||
load: 'Development'. | ||
``` | ||
> Change `release-candidate` to some released version if you want a pinned version | ||
## Using Iceberg | ||
1. Download [pharo VM and image](https://pharo.org/download) | ||
2. Open your Pharo image | ||
3. Open Iceberg | ||
4. Click the *Add* repository button | ||
5. Select *Clone from github.com* and enter `ba-st` as owner name and `Superluminal` | ||
as project name | ||
6. Click *Ok* | ||
7. Select the repository in the main Iceberg window | ||
8. Open the contextual menu and select | ||
*Metacello -> Install baseline of Superluminal ...* | ||
9. Type `Development` and click *Ok* | ||
> After Iceberg cloned a repository, it will be checked-out at the default | ||
> branch (in this case `release-candidate`). If you want to work on a different | ||
> branch or commit perform the checkout before the baseline installation step. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# How to use Superluminal as dependency in a Pharo product | ||
|
||
In order to include **Superluminal** as part of your project, you should reference | ||
the package in your product baseline: | ||
|
||
1. Define the Superluminal repository and version to be used, and the [baseline groups](../reference/Baseline-groups.md) | ||
you want to depend on (usually `Deployment`). | ||
|
||
If you're unsure about what to depend on use the *Dependency Analyzer* | ||
tool to choose an appropriate group including the packages you need. | ||
|
||
2. Create a method like this one in the baseline class of your product: | ||
|
||
```smalltalk | ||
setUpDependencies: spec | ||
spec | ||
baseline: 'Superluminal' | ||
with: [ spec repository: 'github://github://ba-st/Superluminal:v{XX}' ]; | ||
project: 'Superluminal-Deployment' | ||
copyFrom: 'Superluminal' with: [ spec loads: 'Deployment' ] | ||
``` | ||
This will create `Superluminal-Deployment` as a valid target that can be used | ||
as requirement in your own packages. | ||
> Replace `{XX}` with the version you want to depend on | ||
3. Use the new loading target as a requirement on your packages. For example: | ||
```smalltalk | ||
baseline: spec | ||
<baseline> | ||
spec | ||
for: #pharo | ||
do: [ | ||
self setUpDependencies: spec. | ||
spec | ||
package: 'My-Package' | ||
with: [ spec requires: #('Superluminal-Deployment') ] ] | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
# API Client | ||
|
||
When dealing with HTTP APIs, the `API Client` group in the baseline provides | ||
abstractions to ease this kind of interaction. | ||
|
||
`RESTfulAPIClient` is the key abstraction for these features. Some of its | ||
functionality is more useful when dealing with a RESTful API but is usable for | ||
non-RESTful APIs as well. | ||
|
||
`RESTfulAPIClient` provides pooling of the underlying HTTP client, handling of | ||
entity tags, and caching support. | ||
|
||
To create an API client you need to provide a block for creating a basic HTTP | ||
client instance and the caching policy. | ||
|
||
For example: | ||
|
||
```smalltalk | ||
RESTfulAPIClient | ||
buildingHttpClientWith: [ ZnClient new ] | ||
cachingIn: ExpiringCache onLocalMemory | ||
``` | ||
|
||
will instantiate a client pooling ZnClient instances and using an in-memory cache. | ||
|
||
API clients support the following methods: | ||
|
||
- `getAt:configuredBy:withSuccessfulResponseDo:` will execute a GET against the | ||
location in the first argument, configured by the second argument. If the | ||
response is successful the last argument is evaluated with the response's body. | ||
- `postAt:configuredBy:withSuccessfulResponseDo:` will execute a POST against the | ||
location in the first argument, configured by the second argument. If the | ||
response is successful the last argument is evaluated with the response's body. | ||
- `putAt:configuredBy:withSuccessfulResponseDo:` will execute a PUT against the | ||
location in the first argument, configured by the second argument. If | ||
the response is successful, the last argument is evaluated with the response's | ||
body, unless it is `204/No content`. | ||
- `patchAt:configuredBy:withSuccessfulResponseDo:` will execute a PATCH against the | ||
location in the first argument, configured by the second argument. If | ||
the response is successful, the last argument is evaluated with the response's | ||
body. | ||
- `deleteAt:configuredBy:withSuccessfulResponseDo:` will execute a DELETE against | ||
the location in the first argument, configured by the second argument. If the | ||
response is successful the last argument is evaluated with the response's body. | ||
|
||
The configuration blocks follow the builder pattern defined [here](HTTP-Request.md). | ||
|
||
If the execution is unsuccessful an `HTTPClientError` exception is raised with | ||
the corresponding response code. | ||
|
||
It also supports some convenience methods built on the previous ones: | ||
|
||
- `get:accepting:withSuccessfulResponseDo:` will execute a GET against the | ||
location in the first argument, setting the `Accept` header according to the | ||
second argument. If the response is successful the last argument is evaluated | ||
with the response's body. | ||
- `get:withSuccessfulResponseDo:` will execute a GET against the location in the | ||
first argument without further configuration. If the response is successful | ||
the last argument is evaluated with the response's body. | ||
- `post:at:withSuccessfulResponseDo:` will execute a POST, whose body and | ||
`Content-Type` is defined by the entity in the first argument, against the | ||
second argument. If the response is successful the last argument is evaluated | ||
with the response's body. | ||
- `patch:at:withSuccessfulResponseDo:` will execute a PATCH, whose body and | ||
`Content-Type` is defined by the entity in the first argument, against the | ||
second argument. If the response is successful the last argument is evaluated | ||
with the response's body. | ||
- `put:at:` will execute a PUT, whose body and `Content-Type` is defined by the | ||
entity in the first argument, against the second argument. If the response is | ||
successful the last argument is evaluated with the response's body. | ||
- `deleteAt:` will execute a DELETE against the location in the first argument. | ||
If there's an entity tag associated with this location it will set the | ||
`If-Match` header making the delete conditional. | ||
|
||
## Pooling | ||
|
||
Every time an API call is made, if a new authority and port is used | ||
for the invocation the API client will create a connection pool. | ||
|
||
Currently, each pool created has at least one connection alive with | ||
a maximum of 5 connections. | ||
|
||
On API client disposition all the connections in the pool are closed. | ||
|
||
## Entity tags handling | ||
|
||
The `ETag` HTTP response header is an identifier for a specific version of a | ||
resource. It allows caches to be more efficient, and saves bandwidth, as a web | ||
server does not need to send a full response if the content has not changed. On | ||
the other side, if the content has changed, entity tags are useful to help prevent | ||
simultaneous updates of a resource from overwriting each other ("mid-air collisions"). | ||
|
||
If the resource at a given URL changes, a new entity tag value must be generated. | ||
Entity tags are therefore similar to fingerprints and might also be used for tracking | ||
purposes by some servers. A comparison of them allows us to quickly determine | ||
whether two representations of a resource are the same, but they might also be | ||
set to persist indefinitely by a tracking server. | ||
|
||
`RESTfulAPIClient` takes advantage of entity tags, when present, in the following | ||
scenarios: | ||
|
||
- When receiving a successful response including the `ETag` header, both the | ||
entity tag value and the response body are cached in the client. | ||
- When using `deleteAt:` or `patch:at:withSuccessfulResponseDo:` convenience | ||
methods, if an entity tag was previously saved its value is used in an | ||
`If-Match` header preventing deleting or patching a resource whose representation | ||
has changed from the last time it was seen by the client. | ||
- When using any of the `GET`-related methods, if an entity tag was previously | ||
saved its value is used in an `If-None-Match` header. Giving the server the | ||
chance to respond with `204/Not modified` and in that case, the previously | ||
saved body is used as the response body. | ||
|
||
## Caching | ||
|
||
`RESTfulAPIClient` also provides a resource cache. It can be configured to use an | ||
in-memory cache (inside the same image) or a shared cache using [Memcached](https://www.memcached.org/). | ||
|
||
To use an in-memory cache provide it to the API client doing: | ||
|
||
```smalltalk | ||
ExpiringCache onLocalMemory | ||
``` | ||
|
||
and, for a shared cache: | ||
|
||
```smalltalk | ||
ExpiringCache onDistributedMemoryAt: serverList | ||
``` | ||
|
||
where `serverList` is something like `{'127.0.0.1:11211'}` | ||
|
||
Both kinds of caches take into account the `Cache-Control` headers received in | ||
the responses. When the API client receives any of the `GET`-related messages it | ||
looks up in the cache if there's a non-expired resource cached for this location. | ||
If it is, it will reuse that. In case there's no cached resource or the cached one | ||
has expired it will proceed to execute the `GET`. | ||
|
||
Resources are cached when a successful `GET` response is received; and cleared when | ||
any `POST`, `PUT`, `PATCH`, or `DELETE` method is executed against this location, | ||
or when a cached resource is expired. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Baseline Groups | ||
|
||
Superluminal includes the following groups in its Baseline that can be used as | ||
loading targets: | ||
|
||
- `Core` will load the minimal required packages to support `HttpRequest` and | ||
its building interface | ||
- `API Client` will load the packages needed to support API clients, including: | ||
- HTTP client pooling by authority | ||
- ETag caching and automatic support for `If-None-Match` and `If-Match` headers, | ||
and `Not modified` responses | ||
- Caching support according to `Cache-Control` headers, both in-memory or using | ||
memcached | ||
- `Service Discovery` will load the packages needed to support service discovery | ||
against a Consul agent | ||
- `Deployment` will load all the packages needed in a deployed application, which | ||
in this case correspond to `Core` + `API Client` + `Service Discovery` | ||
- `Examples` will load a service discovery-enabled application | ||
- `Tests` will load the test cases | ||
- `Dependent-SUnit-Extensions` will load extensions to SUnit for testing API clients | ||
- `CI` is the group loaded in the continuous integration setup, in this | ||
particular case it is the same as `Tests` | ||
- `Development` will load all the needed packages to develop and contribute to | ||
the project |
Oops, something went wrong.