# Funqy HTTP Binding (Standalone)

The guide walks through quickstart code to show you how you can deploy Funqy as a standalone service and invoke on Funqy functions using HTTP.

| The Funqy HTTP binding is not a replacement for REST over HTTP. Because Funqy needs to be portable across a lot of different protocols and function providers its HTTP binding is very minimalistic and you will lose REST features like linking and the ability to leverage HTTP features like cache-control and conditional GETs. You may want to consider using Quarkus’s Jakarta REST, Spring MVC, or Vert.x Web Reactive Routes support instead, although Funqy will have less overhead than these alternatives (except Vert.x which is still super fast).

## Prerequisites

To complete this guide, you need:

- Roughly 15 minutes

- An IDE

- JDK 17+ installed with `JAVA_HOME` configured appropriately

- Apache Maven 3.9.9

- Optionally the Quarkus CLI if you want to use it

- Read about Funqy Basics. This is a short read!

## The Quickstart

Clone the Git repository: `git clone https://github.com/quarkusio/quarkus-quickstarts.git`, or download an archive.

The solution is located in the `funqy-http-quickstart` directory.

## The Code

If you look at the Java code, you’ll see that there is no HTTP specific API. Its just simple Java methods annotated with `@Funq`. Simple, easy, straightforward.

## Maven Dependencies

To write Funqy HTTP functions, simply include the `quarkus-funqy-http` dependency into your Quarkus `pom.xml` file:

    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-funqy-http</artifactId>
    </dependency>

## Build Project

    mvn clean quarkus:dev

This starts your functions in Quarkus dev mode.

## Execute Funqy HTTP functions

The URL path to execute a function is the function name. For example if your function name is `foo` then the URL path to execute the function would be `/foo`.

The HTTP POST or GET methods can be used to invoke on a function. The return value of the function is marshalled to JSON using the Jackson JSON library. Jackson annotations can be used. If your function has an input parameter, a POST invocation must use JSON as the input type. Jackson is also used here for unmarshalling.

You can invoke the `hello` function defined in PrimitiveFunctions.java by pointing your browser to http://localhost:8080/hello

Invoking the other functions in the quickstart requires an HTTP POST. To execute the `greet` function defined in GreetingFunction.java invoke this curl script.

    curl "http://localhost:8080/greet" \
    -X POST \
    -H "Content-Type: application/json" \
    -d '{"name":"Bill"}'

Primitive types can also be passed as input using the standard JSON mapping for them. To execute the `toLowerCase` function defined in PrimitiveFunctions.java invoke this curl script:

    curl "http://localhost:8080/toLowerCase" \
    -X POST \
    -H "Content-Type: application/json" \
    -d '"HELLO WORLD"'

To execute the `double` function defined in PrimitiveFunctions.java invoke this curl script:

    curl "http://localhost:8080/double" \
    -X POST \
    -H "Content-Type: application/json" \
    -d '2'

## GET Query Parameter Mapping

For GET requests, the Funqy HTTP Binding also has a query parameter mapping for function input parameters. Only bean style classes and `java.util.Map` can be used for your input parameter. For bean style classes, query parameter names are mapped to properties on the bean class. Here’s an example of a simple `Map`:

    @Funq
    public String hello(Map<String, Integer> map) {
    ...
    }

Key values must be a primitive type (except char) or `String`. Values can be primitives (except char), `String`, `OffsetDateTime` or a complex bean style class. For the above example, here’s the corresponding curl request:

    curl "http://localhost:8080/a=1&b=2"

The `map` input parameter of the `hello` function would have the key value pairs: `a`→1, `b`→2.

Bean style classes can also be use as the input parameter type. Here’s an example:

    public class Person {
        String first;
        String last;

        public String getFirst() { return first; }
        public void setFirst(String first) { this.first = first; }
        public String getLast() { return last; }
        public void setLast(String last) { this.last = last; }
    }

    public class MyFunctions {
        @Funq
        public String greet(Person p) {
           return "Hello " + p.getFirst() + " " + p.getLast();
        }
    }

Property values can be any primitive type except `char`. It can also be `String`, and `OffsetDateTime`. `OffsetDateTime` query param values must be in ISO-8601 format.

You can invoke on this using an HTTP GET and query parameters:

    curl "http://localhost:8080/greet?first=Bill&last=Burke"

In the above request, the query parameter names are mapped to corresponding properties in the input class.

The input class can also have nested bean classes. Expanding on the previous example:

    public class Family {
        private Person dad;
        private Person mom;

        public Person getDad() { return dad; }
        public void setDad(Person dad) { this.dad = dad; }
        public Person getMom() { return mom; }
        public void setMom(Person mom) { this.mom = mom; }
    }

    public class MyFunctions {
        @Funq
        public String greet(Family family) {
           ...
        }
    }

In this case, query parameters for nested values use the `.` notation. For example:

    curl "http://localhost:8080/greet?dad.first=John&dad.last=Smith&mom.first=Martha&mom.last=Smith"

`java.util.List` and `Set` are also supported as property values. For example:

    public class Family {
        ...

        List<String> pets;
    }

    public class MyFunctions {
        @Funq
        public String greet(Family family) {
           ...
        }
    }

To invoke a GET request, just list the `pets` query parameter multiple times.

    curl "http://localhost:8080/greet?pets=itchy&pets=scratchy"

For more complex types, `List` and `Set` members must have an identifier in the query parameter. For example:

    public class Family {
        ...

        List<Person> kids;
    }

    public class MyFunctions {
        @Funq
        public String greet(Family family) {
           ...
        }
    }

Each `kids` query parameter must identify the kid they are referencing so that the runtime can figure out which property values go to which members in the list. Here’s the curl request:

    curl "http://localhost:8080/greet?kids.1.first=Buffy&kids.2.first=Charlie"

The above URL uses the value `1` and `2` to identity the target member of the list, but any unique string can be used.

A property can also be a `java.util.Map`. The key of the map can be any primitive type and `String`. For example:

    public class Family {
        ...

        Map<String, String> address;
    }

    public class MyFunctions {
        @Funq
        public String greet(Family family) {
           ...
        }
    }

The corresponding call would look like this:

    curl "http://localhost:8080/greet?address.state=MA&address.city=Boston"

If your `Map` value is a complex type, then just continue the notation by adding the property to set at the end.

    public class Family {
        ...

        Map<String, Address> addresses;
    }

    public class MyFunctions {
        @Funq
        public String greet(Family family) {
           ...
        }
    }

    curl "http://localhost:8080/greet?addresses.home.state=MA&addresses.home.city=Boston"