Standalone Web Applications

Functions could be automatically exported as HTTP endpoints.

The spring-cloud-function-web module has autoconfiguration that activates when it is included in a Spring Boot web application (with MVC support). There is also a spring-cloud-starter-function-web to collect all the optional dependencies in case you just want a simple getting started experience.

With the web configurations activated your app will have an MVC endpoint (on "/" by default, but configurable with spring.cloud.function.web.path) that can be used to access the functions in the application context where function name becomes part of the URL path. The supported content types are plain text and JSON.

It is important to understand that while SCF provides ability to export Functional beans as REST endpoints it is NOT a replacement for Spring MVC/WebFlux etc. It is primarily to accommodate stateless serverless patterns where you simply want to have some stateless functionality to be exposed via HTTP.
Method Path Request Response Status

GET

/{supplier}

-

Items from the named supplier

200 OK

POST

/{consumer}

JSON object or text

Mirrors input and pushes request body into consumer

202 Accepted

PUT

/{consumer}

JSON object or text

Mirrors input and pushes request body into consumer

202 Accepted

DELETE

/{consumer}

JSON object or text

-

204 NO CONTENT

POST

/{function}

JSON object or text

The result of applying the named function

200 OK

PUT

/{function}

JSON object or text

The result of applying the named function

200 OK

GET

/{function}/{item}

-

Convert the item into an object and return the result of applying the function

200 OK

As the table above shows the behavior of the endpoint depends on the method and also the type of incoming request data. When the incoming data is single valued, and the target function is declared as obviously single valued (i.e. not returning a collection or Flux), then the response will also contain a single value. For multi-valued responses the client can ask for a server-sent event stream by sending Accept: text/event-stream.

Functions and consumers that are declared with input and output in Message<?> will see the request headers as message headers, and the output message headers will be converted to HTTP headers. The payload of the Message will be a body or empty string if there is no body or it is null.

When POSTing text the response format might be different with Spring Boot 2.0 and older versions, depending on the content negotiation (provide content type and accept headers for the best results).

See [Testing Functional Applications] to see the details and example on how to test such application.

HTTP Request Parameters

As you have noticed from the previous table, you can pass an argument to a function as path variable (i.e., /{function}/{item}). For example, localhost:8080/uppercase/foo will result in calling uppercase function with its input parameter being foo.

While this is the recommended approach and the one that fits most use cases cases, there are times when you have to deal with HTTP request parameters (e.g., localhost:8080/uppercase/foo?name=Bill) The framework will treat HTTP request parameters similar to the HTTP headers by storing them in the Message headers under the header key http_request_param with its value being a Map of request parameters, so in order to access them your function input signature should accept Message type (e.g., Function<Message<String>, String>). For convenience we provide HeaderUtils.HTTP_REQUEST_PARAM constant.

Function Mapping rules

If there is only a single function (consumer etc.) in the catalog, the name in the path is optional. In other words, providing you only have uppercase function in catalog curl -H "Content-Type: text/plain" localhost:8080/uppercase -d hello and curl -H "Content-Type: text/plain" localhost:8080/ -d hello calls are identical.

Composite functions can be addressed using pipes or commas to separate function names (pipes are legal in URL paths, but a bit awkward to type on the command line). For example, curl -H "Content-Type: text/plain" localhost:8080/uppercase,reverse -d hello.

For cases where there is more than a single function in catalog, each function will be exported and mapped with function name being part of the path (e.g., localhost:8080/uppercase). In this scenario you can still map specific function or function composition to the root path by providing spring.cloud.function.definition property

For example,

--spring.cloud.function.definition=foo|bar

The above property will compose 'foo' and 'bar' function and map the composed function to the "/" path.

The same property will also work for cases where function can not be resolved via URL. For example, your URL may be localhost:8080/uppercase, but there is no uppercase function. However there are function foo and bar. So, in this case localhost:8080/uppercase will resolve to foo|bar. This could be useful especially for cases when URL is used to communicate certain information since there will be Message header called uri with the value of the actual URL, giving user ability to use it for evaluation and computation.

Function Filtering rules

In situations where there are more than one function in catalog there may be a need to only export certain functions or function compositions. In that case you can use the same spring.cloud.function.definition property listing functions you intend to export delimited by ;. Note that in this case nothing will be mapped to the root path and functions that are not listed (including compositions) are not going to be exported

For example,

--spring.cloud.function.definition=foo;bar

This will only export function foo and function bar regardless how many functions are available in catalog (e.g., localhost:8080/foo).

--spring.cloud.function.definition=foo|bar;baz

This will only export function composition foo|bar and function baz regardless how many functions are available in catalog (e.g., localhost:8080/foo,bar).

Http Headers propagation

By default most request HttpHeaders are copied into the response HttpHeaders. If you require to filter out certain headers you can provide the names of those headers using spring.cloud.function.http.ignored-headers delimited by comas. For example, spring.cloud.function.http.ignored-headers=foo,bar

CRUD REST with Spring Cloud Function

By now it should be clear that functions are exported as REST endpoints and can be invoked using various HTTP methods. In other words a single function could be triggered via GET, POST, PUT etc.

However, it is not always desirable and certainly does not fit the CRUD concept. And while SCF does not support and has no intention of supporting all the features of Spring web stack, the framework does provide support for CRUD mappings where a single function could be mapped to a particular HTTP method(s). It is done via spring.cloud.function.http.<method-name> property.

For example,

spring.cloud.function.http.GET=uppercase;reverse;foo|bar
spring.cloud.function.http.POST=reverse
spring.cloud.function.http.DELETE=deleteById

As you can see, here we’re mapping functions to various HTTP methods using the same rules as spring.cloud.function.definition property where “;” allows us to define several functions and “|” signifies function composition.