Skip to content

Commit

Permalink
Add submodules for easier install, improve Makefiles, documentation a…
Browse files Browse the repository at this point in the history
…nd fix bugs in example programs
  • Loading branch information
Nicolas Mora committed Jun 1, 2016
1 parent f5816f8 commit 62f71b9
Show file tree
Hide file tree
Showing 24 changed files with 325 additions and 105 deletions.
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[submodule "lib/orcania"]
path = lib/orcania
url = git@github.com:babelouest/orcania.git
[submodule "lib/yder"]
path = lib/yder
url = git@github.com:babelouest/yder.git
69 changes: 21 additions & 48 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,61 +14,34 @@
#

LIBULFIUS_LOCATION=./src
SIMPLE_EXAMPLE_LOCATION=./examples/simple_example
SHEEP_COUNTER_LOCATION=./examples/sheep_counter
PROXY_EXAMPLE_LOCATION=./examples/proxy_example
REQUEST_EXAMPLE_LOCATION=./examples/request_example
TEST_U_MAP_LOCATION=./examples/test_u_map
INJECTION_EXAMPLE_LOCATION=./examples/injection_example
AUTH_EXAMPLE_LOCATION=./examples/auth_example
STREAM_EXAMPLE_LOCATION=./examples/stream_example
LIBORCANIA_LOCATION=lib/orcania
LIBYDER_LOCATION=lib/yder/src
EXAMPLES_LOCATION=./examples

all: libulfius.so simple_example sheep_counter proxy_example request_example injection_example auth_example test_u_map
all: libulfius.so

debug:
cd $(SIMPLE_EXAMPLE_LOCATION) && $(MAKE) debug
cd $(LIBORCANIA_LOCATION) && $(MAKE) debug
cd $(LIBYDER_LOCATION) && $(MAKE) debug
cd $(LIBULFIUS_LOCATION) && $(MAKE) debug
cd $(PROXY_EXAMPLE_LOCATION) && $(MAKE) debug
cd $(REQUEST_EXAMPLE_LOCATION) && $(MAKE) debug
cd $(INJECTION_EXAMPLE_LOCATION) && $(MAKE) debug
cd $(AUTH_EXAMPLE_LOCATION) && $(MAKE) debug
cd $(STREAM_EXAMPLE_LOCATION) && $(MAKE) debug
cd $(TEST_U_MAP_LOCATION) && $(MAKE) debug

clean:
cd $(LIBORCANIA_LOCATION) && $(MAKE) clean
cd $(LIBYDER_LOCATION) && $(MAKE) clean
cd $(LIBULFIUS_LOCATION) && $(MAKE) clean
cd $(SIMPLE_EXAMPLE_LOCATION) && $(MAKE) clean
cd $(SHEEP_COUNTER_LOCATION) && $(MAKE) clean
cd $(PROXY_EXAMPLE_LOCATION) && $(MAKE) clean
cd $(REQUEST_EXAMPLE_LOCATION) && $(MAKE) clean
cd $(INJECTION_EXAMPLE_LOCATION) && $(MAKE) clean
cd $(AUTH_EXAMPLE_LOCATION) && $(MAKE) clean
cd $(STREAM_EXAMPLE_LOCATION) && $(MAKE) clean
cd $(TEST_U_MAP_LOCATION) && $(MAKE) clean
cd $(EXAMPLES_LOCATION) && $(MAKE) clean

libulfius.so:
cd $(SIMPLE_EXAMPLE_LOCATION) && $(MAKE)

simple_example:
cd $(LIBULFIUS_LOCATION) && $(MAKE)

sheep_counter:
cd $(SHEEP_COUNTER_LOCATION) && $(MAKE)

proxy_example:
cd $(PROXY_EXAMPLE_LOCATION) && $(MAKE)
install:
cd $(LIBORCANIA_LOCATION) && $(MAKE) install
cd $(LIBYDER_LOCATION) && $(MAKE) install
cd $(LIBULFIUS_LOCATION) && $(MAKE) install

request_example:
cd $(REQUEST_EXAMPLE_LOCATION) && $(MAKE)
uninstall:
cd $(LIBORCANIA_LOCATION) && $(MAKE) uninstall
cd $(LIBYDER_LOCATION) && $(MAKE) uninstall
cd $(LIBULFIUS_LOCATION) && $(MAKE) uninstall

injection_example:
cd $(INJECTION_EXAMPLE_LOCATION) && $(MAKE)

stream_example:
cd $(STREAM_EXAMPLE_LOCATION) && $(MAKE)

auth_example:
cd $(AUTH_EXAMPLE_LOCATION) && $(MAKE)

test_u_map:
cd $(TEST_U_MAP_LOCATION) && $(MAKE)
libulfius.so:
cd $(LIBORCANIA_LOCATION) && $(MAKE)
cd $(LIBYDER_LOCATION) && $(MAKE)
cd $(LIBULFIUS_LOCATION) && $(MAKE)
68 changes: 34 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,36 +78,19 @@ To install the external dependencies, for Debian based distributions (Debian, Ub

I write libcurl4-gnutls-dev for the example, but any `libcurl*-dev` library should be sufficent, depending on your needs and configuration.

## Angharad system dependencies

Ulfius depends on [Yder](https://github.com/babelouest/yder) and [Orcania](https://github.com/babelouest/orcania). [Yder](https://github.com/babelouest/yder) is a small log library, useful to log messages in a file, console or syslog, [Orcania](https://github.com/babelouest/orcania) is a smaller library that contains useful functions that I don't want to duplicate in all projects. Simply get Orcania and Yder, then install them.

```shell
$ git clone https://github.com/babelouest/orcania.git
$ cd orcania/src
$ make
$ sudo make install
```

```shell
$ git clone https://github.com/babelouest/yder.git
$ cd yder/src
$ make
$ sudo make install
```

# Installation

Download Ulfius source code from Github, go to src directory, compile and install:
Download Ulfius source code from Github, get the submodules, compile and install:

```shell
$ git clone https://github.com/babelouest/ulfius.git
$ cd ulfius/src
$ cd ulfius/
$ git submodule --init
$ make
$ sudo make install
```

By default, the shared libraries and the header files will be installed in the `/usr/local` location. To change this setting, you can modify the `PREFIX` value in the `Makefile`.
By default, the shared libraries and the header files will be installed in the `/usr/local` location. To change this setting, you can modify the `PREFIX` value in the `src/Makefile`, `lib/orcania/Makefile` and `lib/yder/src/Makefile` files.

# API Documentation

Expand Down Expand Up @@ -289,13 +272,13 @@ int ulfius_add_endpoint_by_val(struct _u_instance * u_instance,
const char * http_method,
const char * url_prefix,
const char * url_format,
int (* auth_function)(const struct _u_request * request, // Input parameters (set by the framework)
struct _u_response * response, // Output parameters (set by the user)
int (* auth_function)(const struct _u_request * request,
struct _u_response * response,
void * auth_data),
void * auth_data,
char * auth_realm,
int (* callback_function)(const struct _u_request * request, // Input parameters (set by the framework)
struct _u_response * response, // Output parameters (set by the user)
int (* callback_function)(const struct _u_request * request,
struct _u_response * response,
void * user_data),
void * user_data);
Expand Down Expand Up @@ -388,7 +371,7 @@ the last 2 will never be reached because the first one will always be a match fo
#### Start webservice
The starting point function are ulfius_start_framework or ulfius_start_secure_framework:
The starting point function are `ulfius_start_framework` or `ulfius_start_secure_framework`:
```c
/**
Expand Down Expand Up @@ -432,7 +415,7 @@ int ulfius_stop_framework(struct _u_instance * u_instance);
### Callback and Authentication functions
The authentication function is the function called for authentication purposes. Ulfius implements basic auth, the user and the password sent by the client are members of `struct _u_request` (see below). In this function, you can implement the authentication method you want by checking the user and password given. If the return value of the authentication function is `U_OK`, the authentication will pass and the callback function will be called then, if the return value is `U_ERROR_UNAUTHORIZED`, the response will be a 401 with the realm parameter given and the response body specified, if the return value is neither `U_OK` nor `U_ERROR_UNAUTHORIZED`, an error 500 will be sent to the client. Authentication functions are optional for endpoints, but if one is set, the auth_realm value must be set too.
The authentication function is the function called for authentication purposes. Ulfius implements basic auth, the user and the password sent by the client are members of `struct _u_request` (see below). In this function, you can implement the authentication method you want by checking the user and password given. If the return value of the authentication function is `U_OK`, the authentication will pass and the callback function will be called then, if the return value is `U_ERROR_UNAUTHORIZED`, the response will be a 401 with the realm parameter given and the response body specified, if the return value is neither `U_OK` nor `U_ERROR_UNAUTHORIZED`, an error 500 will be sent to the client. Authentication functions are optional for endpoints.
The callback function is the function called when a user calls an endpoint managed by your webservice (as defined in your `struct _u_endpoint` list).
Expand Down Expand Up @@ -595,7 +578,7 @@ int ulfius_set_stream_response(struct _u_response * response,
The `jansson` api documentation is available at the following address: [Jansson documentation](https://jansson.readthedocs.org/).
The authentication function return value must be `U_OK` on authentication success, if the credentials are incorrect, you must return `U_ERROR_UNAUTHORIZED` to send an error 401 to the client. All other returned value will send an error 500 to the client.
The authentication function return value must be `U_OK` on authentication success, if the credentials are incorrect, you must return `U_ERROR_UNAUTHORIZED` to send an error 401 to the client, then, the body response will be sent to the client. All other returned value will send an error 500 to the client. If the authentication function return value is `U_OK`, the response body and status will be ignored as the one sent to the client will be the response sent by the callback function.
The callback function return value is `U_OK` on success. If the return value is other than `U_OK`, an error 500 response will be sent to the client.
Expand Down Expand Up @@ -744,7 +727,7 @@ You may be careful with characters encoding if you use non UTF8 characters in yo
### struct _u_map API
The `struct _u_map` is a simple key/value mapping API. The available functions to use this structure are:
The `struct _u_map` is a simple key/value mapping API used in the requests and the response for setting parameters. The available functions to use this structure are:
```c
/**
Expand Down Expand Up @@ -912,7 +895,7 @@ struct _u_map * u_map_copy(const struct _u_map * source);
int u_map_count(const struct _u_map * source);
```

### Send request API
### Send HTTP request API

The functions `int ulfius_send_http_request(const struct _u_request * request, struct _u_response * response)` and `int ulfius_send_http_streaming_request(const struct _u_request * request, struct _u_response * response, size_t (* write_body_function)(void * contents, size_t size, size_t nmemb, void * user_data), void * write_body_data)` are based on `libcurl` api.

Expand All @@ -922,9 +905,9 @@ You can fill the maps in the `_u_request` structure with parameters, they will b

The response parameters is stored into the `_u_response` structure. If you specify NULL for the response structure, the http call will still be made but no response details will be returned. If you use `ulfius_send_http_request`, the response body will be stored in the parameter `response->*body*`, if you use `ulfius_send_http_streaming_request`, the response body will be available in the `write_body_function` specified in the call. The `ulfius_send_http_streaming_request` can be used for streaming data or large response.

Return value is U_OK on success.
Return value is `U_OK` on success.

This function is defined as:
This functions are defined as:

```c
/**
Expand All @@ -933,9 +916,23 @@ This function is defined as:
* return U_OK on success
*/
int ulfius_send_http_request(const struct _u_request * request, struct _u_response * response);

/**
* ulfius_send_http_streaming_request
* Send a HTTP request and store the result into a _u_response
* Except for the body which will be available using write_body_function in the write_body_data
* return U_OK on success
*/
int ulfius_send_http_streaming_request(const struct _u_request * request,
struct _u_response * response,
size_t (* write_body_function)(void * contents,
size_t size,
size_t nmemb,
void * user_data),
void * write_body_data);
```
### Send smtp API
### Send SMTP request API
The function `ulfius_send_smtp_email` is used to send emails using a smtp server. It is based on `libcurl` API.
Expand Down Expand Up @@ -976,5 +973,8 @@ int ulfius_send_smtp_email(const char * host,

### Example source code

See `example` folder for detailed sample source codes.
Example programs are available to see the different functionalities available, see `example` folder for detailed sample source codes and documentation.

### Questions, problems ?

I'm open for questions and suggestions, feel free to open an issue or send a pull request if you feel like it!
44 changes: 44 additions & 0 deletions examples/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#
# Example program
#
# Makefile used to build all programs
#
# Copyright 2014-2015 Nicolas Mora <mail@babelouest.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the MIT License
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#

SIMPLE_EXAMPLE_LOCATION=./simple_example
SHEEP_COUNTER_LOCATION=./sheep_counter
PROXY_EXAMPLE_LOCATION=./proxy_example
REQUEST_EXAMPLE_LOCATION=./request_example
TEST_U_MAP_LOCATION=./test_u_map
INJECTION_EXAMPLE_LOCATION=./injection_example
AUTH_EXAMPLE_LOCATION=./auth_example
STREAM_EXAMPLE_LOCATION=./stream_example

all: debug

debug:
cd $(SIMPLE_EXAMPLE_LOCATION) && $(MAKE) debug
cd $(PROXY_EXAMPLE_LOCATION) && $(MAKE) debug
cd $(REQUEST_EXAMPLE_LOCATION) && $(MAKE) debug
cd $(INJECTION_EXAMPLE_LOCATION) && $(MAKE) debug
cd $(AUTH_EXAMPLE_LOCATION) && $(MAKE) debug
cd $(STREAM_EXAMPLE_LOCATION) && $(MAKE) debug
cd $(TEST_U_MAP_LOCATION) && $(MAKE) debug

clean:
cd $(SIMPLE_EXAMPLE_LOCATION) && $(MAKE) clean
cd $(SHEEP_COUNTER_LOCATION) && $(MAKE) clean
cd $(PROXY_EXAMPLE_LOCATION) && $(MAKE) clean
cd $(REQUEST_EXAMPLE_LOCATION) && $(MAKE) clean
cd $(INJECTION_EXAMPLE_LOCATION) && $(MAKE) clean
cd $(AUTH_EXAMPLE_LOCATION) && $(MAKE) clean
cd $(STREAM_EXAMPLE_LOCATION) && $(MAKE) clean
cd $(TEST_U_MAP_LOCATION) && $(MAKE) clean
18 changes: 18 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Ulfius Franework example programs

Those programs require ulfius to be installed with its dependencies. To do so, in the root folder, run `make && sudo make install` to compile and install the library. Refer to the `README.md` for more information.

Each program implement some functionalities provided by Ulfius, such as url parsing, request filling and response manipulation. For each example program, you can look at its `README.md`. In general, a simple `make ` or `make test` is sufficient to run the example program.

## Example programs available

The example programs were developped to help implementing the functionnalities of the framework and test them. The tested functionnalities are:

- `simple_example`: endpoint tests, url parameters, body parameters, json body parameters and cookies
- `sheep_counter`: file server, upload file
- `injection_example`: endpoints injection and remove during the program execution
- `proxy_example`: proxyfies calls to anither url
- `auth_example`: HTTP Basic Auth
- `stream_example`: data streaming (server and client side)
- `request_example`: send http and smtp requests
- `test_u_map`: struct _u_map tests
20 changes: 20 additions & 0 deletions examples/auth_example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Authentication example

Provides an application that implement basic authentication

## Compile and run

```bash
$ make
$ ./auth_server
```

## Usage

Open in your browser the url `http://localhost:2884/auth/basic`, then on the authentication prompt, enter the `USER` and `PASSWORD` specified in `auth_server.c` (default test/testpassword) to be authenticated and allowed to access the endpoint.

In another console, you can run the client program to test the use cases

```bash
$ ./auth_client
```
18 changes: 9 additions & 9 deletions examples/auth_example/auth_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,16 @@ int main (int argc, char **argv) {
req_list[3].http_url = strdup(SERVER_URL "/404");

ulfius_init_request(&req_list[4]);
req_list[1].http_verb = strdup("GET");
req_list[1].http_url = strdup(SERVER_URL_DEFAULT);
req_list[1].auth_basic_user = strdup("test");
req_list[1].auth_basic_password = strdup("testpassword");
req_list[4].http_verb = strdup("GET");
req_list[4].http_url = strdup(SERVER_URL_DEFAULT);
req_list[4].auth_basic_user = strdup("test");
req_list[4].auth_basic_password = strdup("testpassword");

ulfius_init_request(&req_list[4]);
req_list[2].http_verb = strdup("GET");
req_list[2].http_url = strdup(SERVER_URL_DEFAULT);
req_list[2].auth_basic_user = strdup("test");
req_list[2].auth_basic_password = strdup("wrongpassword");
ulfius_init_request(&req_list[5]);
req_list[5].http_verb = strdup("GET");
req_list[5].http_url = strdup(SERVER_URL_DEFAULT);
req_list[5].auth_basic_user = strdup("test");
req_list[5].auth_basic_password = strdup("wrongpassword");

printf("Press <enter> to run auth tests no authentication\n");
getchar();
Expand Down
30 changes: 30 additions & 0 deletions examples/injection_example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Injection example

Provides an example program that will add and remove endpoints during the execution

## Compile and run

```bash
$ make test
```

## Usage

Right after starting the program, the endpoints available are the following:

- `GET http://localhost:4528/inject/first`
- `GET http://localhost:4528/inject/second`
- `GET http://localhost:4528/inject/third`

On the program console, press `<enter>` one time will add this new endpoint:
- `GET http://localhost:4528/inject/fourth`

Press `<enter>` again to add the following endpoint:
- `GET http://localhost:4528/inject/fifth`

Press `<enter>` to remove the following endpoint:
- `GET http://localhost:4528/inject/fourth`

Then press `<enter>` to quit the application

You can test the presence or absence of the specified endpoints between each step.
4 changes: 2 additions & 2 deletions examples/injection_example/injection_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ int main (int argc, char **argv) {

y_log_message(Y_LOG_LEVEL_DEBUG, "Press <enter> to inject %s/fourth endpoint", PREFIX);
getchar();
ulfius_add_endpoint_by_val(&instance, "GET", PREFIX, NULL, NULL, NULL, "/fourth", &callback_fourth, NULL);
ulfius_add_endpoint_by_val(&instance, "GET", PREFIX, "/fourth", NULL, NULL, NULL, &callback_fourth, NULL);

y_log_message(Y_LOG_LEVEL_DEBUG, "Press <enter> to inject %s/fifth endpoint", PREFIX);
getchar();
ulfius_add_endpoint_by_val(&instance, "GET", PREFIX, NULL, NULL, NULL, "/fifth", &callback_fifth, NULL);
ulfius_add_endpoint_by_val(&instance, "GET", PREFIX, "/fifth", NULL, NULL, NULL, &callback_fifth, NULL);

y_log_message(Y_LOG_LEVEL_DEBUG, "Press <enter> to remove %s/fourth endpoint", PREFIX);
getchar();
Expand Down
Loading

0 comments on commit 62f71b9

Please sign in to comment.