NAV
lhc - LFE Little HTTP Client library
lhc - LFE Little HTTP Client library

Introduction

Little (LFE) HTTP Client – A light-weight LFE wrapper around lhttpc

lhc is library is meant to be a dead-simple HTTP client for LFE projects. That’s all there is to it. It uses lhttpc under the hood, which can be a little cumbersome for those new to Erlang when used directly; as such, lhc will likely provide a welcome alternative.

Dependencies

To use lhc, you need to have the following:

Since version 0.2.0, the lhc library has moved to using rebar3 and no longer supports the old version of rebar. If, for whatever reason, your project cannot use rebar3, you’ll need to use version 0.1.0 of the lhc library.

Installation

To use the rebar3 LFE plugin, update your rebar.config file like the following:

{plugins, [
   {'lfe-compile', ".*", {git, "https://github.com/lfe-rebar3/compile.git", {tag, "0.2.0"}}}
  ]}.
{provider_hooks, [
   {pre, [{compile, {lfe, compile}}]}
  ]}.

Then update the deps directive in your rebar.config to pull down the latest lhc:

{deps, [
...
{lhc, ".*",
  {git, "git@github.com:lfex/lhc.git", "0.2.0"}}
  ]}.

Once your project has added the lhc dependency, you’re ready to execute the rebar3 command for compiling LFE projects:

$ rebar3 lfe compile

If you want to compile both LFE and any Erlang code you have in your project, you can do both with one command:

$ rebar3 compile

Since lhc now uses rebar3, you’ll need to configure your project’s rebar.config file to pull down the necessary rebar3 plugins. A good example of this is the rebar.config file for the lcfg project. In particular, you’ll want to have the same plugins and provider_hooks directives.

See notes to the right for specifics.

The API

Each of the API functions that map to an HTTP verb have at least one arity that supports setting lhc options which are passed to lhc:request. These options may have zero or more of the following:

The lhc examples below are run against a YAWS REST server demo store. You can download and run the “store” yourself when you clone the repo.

For POSTing data, we use the ljson LFE library. To make this available to your project, simply add it to your rebar.config file, per the instructions on the ljson project README.

start

It is required to start lhc before using the API:

> (lhc:start)
(#(inets ok) #(ssl ok) #(lhttpc ok) #(lhc ok))

If you attempt to use the API without having first started it, you will see errors like the following:

> (lhc:get "http://localhost:8000/demos/store3/orders")
#(error
  #(exit
    #(noproc
      #(gen_server call
        (undefined #(socket <0.35.0> "google.com" 80 false) infinity)))
    (#(lhttpc_manager ensure_call 6
       (#(file "src/lhttpc_manager.erl") #(line 234)))
     #(lhttpc_client execute 9 (#(file "src/lhttpc_client.erl") #(line 158)))
     #(lhttpc_client request 9 (#(file "src/lhttpc_client.erl") #(line 99)))
     #(proc_lib init_p_do_apply 3 (#(file "proc_lib.erl") #(line 239))))))

This function simply starts the lhc LFE HTTP client. This is required for any use of the lhc client library.

get

Perform a simple GET:

> (lhc:get "http://localhost:8000/demos/store3/orders")
"{\"result\": \"You got a list of orders.\"}"
>

Depending upon the return option (default being body) and callback option, each of these will return a parsed result iof the content obtained by lhttpc.

To just get the headers from the server:

> (lhc:head "http://localhost:8000/demos/store3/")
(#("Content-Type" "application/json")
 #("Date" "Thu, 27 Aug 2015 14:39:31 GMT")
 #("Server" "Yaws 2.0"))
>

Returns just the parsed headers of the result from lhttpc. By defualt, this is a list of tuples, each being a key/value pair of header name and head value.

post

To POST, we first create a payload. The demo REST API we’re testing against can take any string value, but many applications will expect JSON data. Let’s use JSON here:

> (set payload (ljson:encode '(#(make #"Volvo") #(model #"P1800"))))
#"{"make":"Volvo","model":"P1800"}"
>

With our payload in hand, we can now POST to create a new order:

> (lhc:post "http://localhost:8000/demos/store3/order" payload)
"{\"result\": \"{\"order-id\": 124}\"}"
>

put

To PUT, we first create a payload similar to what we did for POST but with the modified data we want:

> (set payload (ljson:encode '(#(make #"Volvo") #(model #"2015 P1800"))))
#"{"make":"Volvo","model":"2015 P1800"}"
>

We can now PUT to update our order:

> (lhc:put "http://localhost:8000/demos/store3/order/124" payload)
"{\"result\": \"You updated all of order 124.\"}"
>

delete

DELETEing is as simple as passing the appropriate URL:

> (lhc:delete "http://localhost:8000/demos/store3/order/124")
"{\"result\": \"You deleted order 124.\"}"
>

trace

Note that TRACE isn’t implemented in YAWS so we don’t have example code to share. Likewise, lhc:trace is untested against a server implementing TRACE – please let us know if you run into usage problems with this function.

options

lhc provides support for requesting the allowed methods for a given URL:

> (lhc:options "http://localhost:8000/demos/store3/order/124")
"{\"result\": \"You got the allowed method for order/124: GET, PUT, POST, DELETE, and OPTIONS.\"}"

connect

TBD

(Note that this HTTP verb is not supported by YAWS, so we’ll likely save it for very last.)

patch

Let’s define the partial data we want to send:

> (set payload (ljson:encode '(#(model #"2015 P1800"))))
#"{"model":"2015 P1800"}"
>

We can now PATCH our order, updating only the part that we wanted to change:

> (lhc:patch "http://localhost:8000/demos/store3/order/124" payload)
"{\"result\": \"You updated part of order 124.\"}"
>

PATCH is useful for large data sets where you only one a part of the data updated. You can use PATCH to update just the bits you’re interested in, without having to send the entire payload like is recommended with PUT.

request

[Code ready, need docs]

parse-results

[Code ready, need docs]

Custom Results Parsing

[Code ready, need docs]

From Erlang

Basic usage from Erlang is straight-forward:

1> lhc:start().
[{inets,ok},{ssl,ok},{lhttpc,ok},{lhc,ok}]
2> lhc:get("http://localhost:8000/demos/store3/orders").
"{\"result\": \"You got a list of orders.\"}"
3> Payload = ljson:encode([{make,<<"Volvo">>},{model,<<"P1800">>}]).
<<"{\"make\":\"Volvo\",\"model\":\"P1800\"}">>
4> lhc:post("http://localhost:8000/demos/store3/order", Payload).
"{\"result\": \"{\"order-id\": 124}\"}"

Using lhc from Erlang is very straight-forward; there aren’t even hypens in most module or function names, so no need to escape any atoms!

Why would you want to, you ask? Well, it might be convenient to use a library that offers consistent usage patterns (and function calls) across a selection of HTTP clients in the Erlang ecosystem. You and your developers could write your HTTP code once, and then change backend clients as the needs arose, without having to change any code (just some small configuration settings).

Take a look at the sample usage to the right to get a sense of using lhc from Erlang.

Backends

lhc supports a handfule of backends, with more future ones planned.

Current backends are:

Planned backends currently include the following:

Selecting

Edit the backend value in the lhc section of your lfe.config file. See the lhc lfe.config for an example of this. Once edited, running start will use that value:

> (lhc:start)
(#(inets ok) #(ssl ok) #(lhttpc ok) #(lhc ok))
> (lhc:get-backend)
lhttpc
>

You can also start lhc with your preferred backend:

> (lhc:start 'httpc)
(#(inets ok) #(ssl ok) #(lhc ok))
>

You can change backends at any time:

> (lhc:change-backend 'lhttpc)
(#(backend #(previous httpc) #(current lhttpc)))
>

Bakends my be selected one of three ways:

Backend Information

Find out which backend you are using:

> (lhc:get-backend)
lhttpc
>

Find out which backend is configured in your lfe.config file:

> (lhc:get-backend-cfg)
lhttpc

Find out which module holds the backend functions:

> (lhc:get-backend-module)
lhc-backend

Several convenience functions are provided in support of lhc backends.

See examples to the right.

User Agent

The lhc user agent string:

"LFE Little HTTP Client/0.1.0 (LFE 0.10.0-dev; Erlang 18; backend=lhttpc) (+http://github.com/lfex/lhc)"

The lhc user agent will show up in any HTTP server log files where client user agent strings are recorded. To the right is an example of the lhc user agent string.

Previous Versions

Documentation is available for all previous releases:

License

Copyright © 2014-2015 Duncan McGreggor oubiwann@gmail.com

Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.