package com.github.kristofa.test.http;
import java.nio.charset.Charset;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
/**
* {@link HttpResponseProvider} that keeps expected request/responses in memory. Its purpose is to match simple requests that
* can be easily programmatically defined in code. It supports matching:
* <p/>
* <ul>
* <li>HTTP Method (GET, PUT, POST, DELETE)</li>
* <li>Path (including query parmeters)</li>
* <li>Content-Type http header</li>
* <li>Request Entity</li>
* </ul>
* It does not support other http headers than Content-Type. If other http header parameters are present in HttpRequest they
* will be ignored.
*
* @see MockHttpServer
* @author kristof
*/
public class SimpleHttpResponseProvider extends AbstractHttpResponseProvider {
private static final String CONTENT_TYPE_HTTP_HEADER_NAME = "Content-Type";
private HttpRequestImpl latestRequest;
public SimpleHttpResponseProvider() {
addHttpRequestMatchingFilter(new AllExceptContentTypeHeaderFilter());
}
/**
* Provide an expected request with content.
*
* @param method HTTP method.
* @param path Path. Path can contain query parameters, eg: path?a=b&b=c
* @param contentType Content type.
* @param requestEntity Request entity as string.
* @return current {@link SimpleHttpResponseProvider}. Allows chaining calls.
*/
public SimpleHttpResponseProvider expect(final Method method, final String path, final String contentType,
final String requestEntity) {
latestRequest = new HttpRequestImpl();
latestRequest.method(method).content(requestEntity.getBytes())
.httpMessageHeader(CONTENT_TYPE_HTTP_HEADER_NAME, contentType);
extractAndSetQueryParams(latestRequest, path);
return this;
}
/**
* Provide an expected request without content.
*
* @param method HTTP method.
* @param path Path. Path can contain query parameters, eg: path?a=b&b=c
* @return current {@link SimpleHttpResponseProvider}. Allows chaining calls.
*/
public SimpleHttpResponseProvider expect(final Method method, final String path) {
latestRequest = new HttpRequestImpl();
latestRequest.method(method);
extractAndSetQueryParams(latestRequest, path);
return this;
}
/**
* Provide expected response for latest given request.
*
* @param httpCode Http response code.
* @param contentType Content type.
* @param requestEntity Data.
* @return current {@link SimpleHttpResponseProvider}. Allows chaining calls.
*/
public SimpleHttpResponseProvider respondWith(final int httpCode, final String contentType, final String requestEntity) {
final HttpResponseImpl response =
new HttpResponseImpl(httpCode, contentType, requestEntity == null ? null : requestEntity.getBytes());
addExpected(latestRequest, new DefaultHttpResponseProxy(response));
return this;
}
/**
* Reset the response provider to its original state
*/
public void reset() {
resetState();
}
private void extractAndSetQueryParams(final HttpRequestImpl request, final String path) {
final int indexOfQuestionMark = path.indexOf("?");
if (indexOfQuestionMark >= 0) {
final String newPath = path.substring(0, indexOfQuestionMark);
final String queryParams = path.substring(indexOfQuestionMark + 1);
final List<NameValuePair> parameters = URLEncodedUtils.parse(queryParams, Charset.forName("UTF-8"));
for (final NameValuePair parameter : parameters) {
request.queryParameter(parameter.getName(), parameter.getValue());
}
request.path(newPath);
} else {
request.path(path);
}
}
}