# Socket APIs Moco mainly focuses on server configuration. There are only two kinds of API right now: **Request** and **Response**. That means if we get the expected request and then return our response. Now, you can see a Moco reference in details. **WARNING** the json configuration below is just a snippet for one pair of request and response, instead of the whole configuration file. Table of Contents ================= * [Composite Java API Design](#composite-java-api-design) * [Description as comment](#description-as-comment) * [Request](#request) * [Content](#content) * [XML](#xml) * [XPath](#xpath) * [JSON Request](#json-request) * [JSON Text](#json-text) * [JSON Text Shortcut](#json-text-shortcut) * [JSON File](#json-file) * [JSONPath](#jsonpath) * [Operator](#operator) * [Match](#match) * [Starts With](#starts-with) * [Ends With](#ends-with) * [Contain](#contain) * [Exist](#exist) * [Response](#response) * [Content](#content-1) * [Latency](#latency) * [Sequence](#sequence) * [JSON Response](#json-response) * [Template(Beta)](#templatebeta) * [Content](#content-2) * [Custom Variable](#custom-variable) * [File Name Template](#file-name-template) ## Composite Java API Design Moco Java API is designed in functional fashion which means you can composite any request or response easily. ```java server.request(and(by(uri("/target")), by(version(VERSION_1_0)))).response(with(text("foo")), header("Content-Type", "text/html")); ``` ## Description as comment **@Since 0.7** In all JSON APIs, you can use **description** to describe what is this session for. It's just used as comment, which will be ignored in runtime. ```json [ { "description": "any response", "response": { "text": "foo" } } ] ``` ## Request ### Content **@Since 0.7** If you want to response according to request content, Moco server can be configured as following: * Java API ```java server.request(by("foo")).response("bar"); ``` * JSON ```json { "request" : { "text" : "foo" }, "response" : { "text" : "bar" } } ``` If request content is too large, you can put it in a file: * Java API ```java server.request(by(file("foo.request"))).response("bar"); ``` * JSON ```json { "request" : { "file" : "foo.request" }, "response" : { "text" : "bar" } } ``` ### XML **@Since 0.7** XML is a popular format for Web Services. When a request is in XML, only the XML structure is important in most cases and whitespace can be ignored. The `xml` operator can be used for this case. * Java API ```java server.request(xml(text("1"))).response("foo"); ``` * JSON ```json { "request": { "text": { "xml": "1" } }, "response": { "text": "foo" } } ``` **NOTE**: Please escape the quote in text. The large request can be put into a file: ```json { "request": { "file": { "xml": "your_file.xml" } }, "response": { "text": "foo" } } ``` ### XPath **@Since 0.7** For the XML/HTML request, Moco allows us to match request with XPath. * Java API ```java server.request(eq(xpath("/request/parameters/id/text()"), "1")).response("bar"); ``` * JSON ```json { "request" : { "method" : "post", "xpaths" : { "/request/parameters/id/text()" : "1" } }, "response" : { "text" : "bar" } } ``` ### JSON Request #### JSON Text **@Since 0.7** Json is rising with RESTful style architecture. Just like XML, in the most case, only JSON structure is important, so `json` operator can be used. * Java API ```java server.request(json(text("{\"foo\":\"bar\"}"))).response("foo"); ``` * JSON ```json { "request": { "text": { "json": "{\"foo\":\"bar\"}" } }, "response": { "text": "foo" } } ``` **NOTE**: Please escape the quote in text. #### JSON Text Shortcut **@Since 0.9.2** As you have seen, it is so boring to write json with escape character, especially in json configuration. So you can try the json shortcut. The upper case could be rewritten as following: * JSON ```json { "request": { "json": { "foo": "bar" } }, "response": { "text": "foo" } } ``` #### JSON File **@Since 0.7** The large request can be put into a file: * Java API ```java server.request(json(file("your_file.json"))).response("foo"); ``` * JSON ```json { "request": { "file": { "json": "your_file.json" } }, "response": { "text": "foo" } } ``` ### JSONPath **@Since 0.7** For the JSON/HTML request, Moco allows us to match request with JSONPath. * Java API ```java server.request(eq(jsonPath("$.book[*].price"), "1")).response("response_for_json_path_request"); ``` * JSON ```json { "request": { "json_paths": { "$.book[*].price": "1" } }, "response": { "text": "response_for_json_path_request" } } ``` ### Operator Moco also supports some operators which helps you write your expectation easily. #### Match **@Since 0.7** You may want to match your request with regular expression, **match** could be your helper: * Java API ```java server.request(match(text("/\\w*/foo"))).response("bar"); ``` * JSON ```json { "request": { "text": { "match": "/\\w*/foo" } }, "response": { "text": "bar" } } ``` Moco is implemented by Java regular expression, you can refer [here](http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html) for more details. #### Starts With **@Since 0.9.2** **starsWith** operator can help you decide if the request information starts with a piece of text. * Java API ```java server.request(startsWith(text("/foo"))).response("bar"); ``` * JSON ```json { "request": { "text": { "startsWith": "/foo" } }, "response": { "text": "bar" } } ``` #### Ends With **@Since 0.9.2** **endsWith** operator can help you decide if the request information ends with a piece of text. * Java API ```java server.request(endsWith(text("foo"))).response("bar"); ``` * JSON ```json { "request": { "text": { "endsWith": "foo" } }, "response": { "text": "bar" } } ``` #### Contain **@Since 0.9.2** **contain** operator helps you know whether the request information contains a piece of text. * Java API ```java server.request(contain(text("foo"))).response("bar"); ``` * JSON ```json { "request": { "text": { "contain": "foo" } }, "response": { "text": "bar" } } ``` #### Exist **@Since 0.9.2** **exist** operator is used to decide whether the request information exists. * Java API ```java server.request(exist(header("foo"))).response("bar"); ``` * JSON ```json { "request": { "headers": { "foo": { "exist" : "true" } }, "response": { "text": "bar" } } ``` For JSON API, you can decide whether the information does not exist. * JSON ```json { "request": { "headers": { "foo": { "exist" : "not" } }, "response": { "text": "bar" } } ``` ## Response ### Content **@Since 0.7** As you have seen in previous example, response with content is pretty easy. * Java API ```java server.request(by("foo")).response("bar"); ``` * JSON ```json { "request" : { "text" : "foo" }, "response" : { "text" : "bar" } } ``` The same as request, you can response with a file if content is too large to put in a string. * Java API ```java server.request(by("foo")).response(file("bar.response")); ``` * JSON ```json { "request" : { "text" : "foo" }, "response" : { "file" : "bar.response" } } ``` ### Latency **@Since 0.7** Sometimes, we need a latency to simulate slow server side operation. * Java API ```java server.request(by("foo")).response(latency(5000)); ``` * JSON ```json { "request" : { "text" : "foo" }, "response" : { "latency" : 5000 } } ``` **@Since 0.10.1** It's easy to setup latency with time unit. ```java server.response(latency(1, TimeUnit.SECONDS)); ``` ### Sequence **@Since 0.7** Sometimes, we want to simulate a real-world operation which change server side resource. For example: * First time you request a resource and "foo" is returned * We update this resource * Again request the same URL, updated content, e.g. "bar" is expected. We can do that by ```java server.request(by(text("/foo"))).response(seq("foo", "bar", "blah")); ``` ### JSON Response JSON response is the API without Java API, so if response is json, we don't have to write json with escape character. Hint, json api will setup Content-Type header as well. ```json { "request": { "text": "json" }, "response": { "json": { "foo" : "bar" } } } ``` ## Template(Beta) **Note**: Template is an experimental feature which could be changed a lot in the future. Feel free to tell how it helps or you need more features in template. Sometimes, we need to customize our response based on something, e.g. response should have same header with request. The goal can be reached by template: ### Content **@Since 0.8** All request content can be used in template with "req.content" * Java ```java server.request(by(text("template"))).response(template("${req.content}")); ``` * JSON ```json { "request": { "text": "template" }, "response": { "text": { "template": "${req.content}" } } } ``` ### Custom Variable **@Since 0.9.1** You can provide your own variables in your template. * Java ```java server.request(by(text("template"))).response(template("${'foo'}", "foo", "bar")); ``` * JSON ```json { "request": { "text": "template" }, "response": { "text": { "template": { "with" : "${'foo'}", "vars" : { "foo" : "bar" } } } } } ``` **@Since 0.10.0** You can also use extractor to extract information from request. * Java ```java server.request(by(text("template"))).response(template("${'foo'}", "foo", jsonPath("$.book[*].price"))); ``` * JSON ```json { "request": { "text": "template" }, "response": { "text": { "template": { "with" : "${'foo'}", "vars" : { "foo" : { "json_paths": "$.book[*].price" } } } } } } ``` Other extractors, e.g. xpath also work here. ### File Name Template Template can also be used in file name, thus response can be different based on different request. * Java ```java server.response(file(template("${req.headers['foo'].txt"))); ``` * JSON ```json [ { "response": { "file": { "name": { "template": "${req.content}.txt" } } } } ] ```