mirror of https://github.com/apache/nifi.git
NIFI-3508: Added support for PATCH identical to that of PUT/POST
This closes #1522. Signed-off-by: ijokarumawak <ijokarumawak@apache.org>
This commit is contained in:
parent
4f49095d75
commit
f9c4d3ce3a
|
@ -95,7 +95,7 @@ import org.joda.time.format.DateTimeFormatter;
|
|||
@Tags({"http", "https", "rest", "client"})
|
||||
@InputRequirement(Requirement.INPUT_ALLOWED)
|
||||
@CapabilityDescription("An HTTP client processor which can interact with a configurable HTTP Endpoint. The destination URL and HTTP Method are configurable."
|
||||
+ " FlowFile attributes are converted to HTTP headers and the FlowFile contents are included as the body of the request (if the HTTP Method is PUT or POST).")
|
||||
+ " FlowFile attributes are converted to HTTP headers and the FlowFile contents are included as the body of the request (if the HTTP Method is PUT, POST or PATCH).")
|
||||
@WritesAttributes({
|
||||
@WritesAttribute(attribute = "invokehttp.status.code", description = "The status code that is returned"),
|
||||
@WritesAttribute(attribute = "invokehttp.status.message", description = "The status message that is returned"),
|
||||
|
@ -138,8 +138,8 @@ public final class InvokeHTTP extends AbstractProcessor {
|
|||
// properties
|
||||
public static final PropertyDescriptor PROP_METHOD = new PropertyDescriptor.Builder()
|
||||
.name("HTTP Method")
|
||||
.description("HTTP request method (GET, POST, PUT, DELETE, HEAD, OPTIONS). Arbitrary methods are also supported. "
|
||||
+ "Methods other than POST and PUT will be sent without a message body.")
|
||||
.description("HTTP request method (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS). Arbitrary methods are also supported. "
|
||||
+ "Methods other than POST, PUT and PATCH will be sent without a message body.")
|
||||
.required(true)
|
||||
.defaultValue("GET")
|
||||
.expressionLanguageSupported(true)
|
||||
|
@ -238,7 +238,7 @@ public final class InvokeHTTP extends AbstractProcessor {
|
|||
|
||||
public static final PropertyDescriptor PROP_CONTENT_TYPE = new PropertyDescriptor.Builder()
|
||||
.name("Content-Type")
|
||||
.description("The Content-Type to specify for when content is being transmitted through a PUT or POST. "
|
||||
.description("The Content-Type to specify for when content is being transmitted through a PUT, POST or PATCH. "
|
||||
+ "In the case of an empty value after evaluating an expression language expression, Content-Type defaults to " + DEFAULT_CONTENT_TYPE)
|
||||
.required(true)
|
||||
.expressionLanguageSupported(true)
|
||||
|
@ -249,7 +249,7 @@ public final class InvokeHTTP extends AbstractProcessor {
|
|||
public static final PropertyDescriptor PROP_SEND_BODY = new PropertyDescriptor.Builder()
|
||||
.name("send-message-body")
|
||||
.displayName("Send Message Body")
|
||||
.description("If true, sends the HTTP message body on POST/PUT requests (default). If false, suppresses the message body and content-type header for these requests.")
|
||||
.description("If true, sends the HTTP message body on POST/PUT/PATCH requests (default). If false, suppresses the message body and content-type header for these requests.")
|
||||
.defaultValue("true")
|
||||
.allowableValues("true", "false")
|
||||
.required(false)
|
||||
|
@ -343,7 +343,7 @@ public final class InvokeHTTP extends AbstractProcessor {
|
|||
|
||||
public static final PropertyDescriptor PROP_USE_CHUNKED_ENCODING = new PropertyDescriptor.Builder()
|
||||
.name("Use Chunked Encoding")
|
||||
.description("When POST'ing or PUT'ing content set this property to true in order to not pass the 'Content-length' header and instead send 'Transfer-Encoding' with "
|
||||
.description("When POST'ing, PUT'ing or PATCH'ing content set this property to true in order to not pass the 'Content-length' header and instead send 'Transfer-Encoding' with "
|
||||
+ "a value of 'chunked'. This will enable the data transfer mechanism which was introduced in HTTP 1.1 to pass data of unknown lengths in chunks.")
|
||||
.required(true)
|
||||
.defaultValue("false")
|
||||
|
@ -596,7 +596,7 @@ public final class InvokeHTTP extends AbstractProcessor {
|
|||
}
|
||||
|
||||
String request = context.getProperty(PROP_METHOD).evaluateAttributeExpressions().getValue().toUpperCase();
|
||||
if ("POST".equals(request) || "PUT".equals(request)) {
|
||||
if ("POST".equals(request) || "PUT".equals(request) || "PATCH".equals(request)) {
|
||||
return;
|
||||
} else if (putToAttribute) {
|
||||
requestFlowFile = session.create();
|
||||
|
@ -809,6 +809,10 @@ public final class InvokeHTTP extends AbstractProcessor {
|
|||
requestBody = getRequestBodyToSend(session, context, requestFlowFile);
|
||||
requestBuilder = requestBuilder.put(requestBody);
|
||||
break;
|
||||
case "PATCH":
|
||||
requestBody = getRequestBodyToSend(session, context, requestFlowFile);
|
||||
requestBuilder = requestBuilder.patch(requestBody);
|
||||
break;
|
||||
case "HEAD":
|
||||
requestBuilder = requestBuilder.head();
|
||||
break;
|
||||
|
|
|
@ -1114,6 +1114,93 @@ public abstract class TestInvokeHttpCommon {
|
|||
Assert.assertEquals(expected1, actual1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatch() throws Exception {
|
||||
addHandler(new MutativeMethodHandler(MutativeMethod.PATCH));
|
||||
|
||||
runner.setProperty(InvokeHTTP.PROP_METHOD, "PATCH");
|
||||
runner.setProperty(InvokeHTTP.PROP_URL, url + "/patch");
|
||||
|
||||
createFlowFiles(runner);
|
||||
|
||||
runner.run();
|
||||
runner.assertTransferCount(InvokeHTTP.REL_SUCCESS_REQ, 1);
|
||||
runner.assertTransferCount(InvokeHTTP.REL_RESPONSE, 1);
|
||||
runner.assertTransferCount(InvokeHTTP.REL_RETRY, 0);
|
||||
runner.assertTransferCount(InvokeHTTP.REL_NO_RETRY, 0);
|
||||
runner.assertTransferCount(InvokeHTTP.REL_FAILURE, 0);
|
||||
runner.assertPenalizeCount(0);
|
||||
|
||||
final MockFlowFile bundle = runner.getFlowFilesForRelationship(InvokeHTTP.REL_SUCCESS_REQ).get(0);
|
||||
bundle.assertContentEquals("Hello".getBytes("UTF-8"));
|
||||
bundle.assertAttributeEquals(InvokeHTTP.STATUS_CODE, "200");
|
||||
bundle.assertAttributeEquals(InvokeHTTP.STATUS_MESSAGE, "OK");
|
||||
bundle.assertAttributeEquals("Foo", "Bar");
|
||||
|
||||
final MockFlowFile bundle1 = runner.getFlowFilesForRelationship(InvokeHTTP.REL_RESPONSE).get(0);
|
||||
bundle1.assertContentEquals("".getBytes("UTF-8"));
|
||||
bundle1.assertAttributeEquals(InvokeHTTP.STATUS_CODE, "200");
|
||||
bundle1.assertAttributeEquals(InvokeHTTP.STATUS_MESSAGE, "OK");
|
||||
bundle1.assertAttributeEquals("Foo", "Bar");
|
||||
bundle1.assertAttributeNotExists("Content-Type");
|
||||
|
||||
final String actual1 = new String(bundle1.toByteArray(), StandardCharsets.UTF_8);
|
||||
final String expected1 = "";
|
||||
Assert.assertEquals(expected1, actual1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchWithMimeType() throws Exception {
|
||||
final String suppliedMimeType = "text/plain";
|
||||
addHandler(new MutativeMethodHandler(MutativeMethod.PATCH, suppliedMimeType));
|
||||
|
||||
runner.setProperty(InvokeHTTP.PROP_METHOD, "PATCH");
|
||||
runner.setProperty(InvokeHTTP.PROP_URL, url + "/patch");
|
||||
|
||||
final Map<String, String> attrs = new HashMap<>();
|
||||
|
||||
attrs.put(CoreAttributes.MIME_TYPE.key(), suppliedMimeType);
|
||||
runner.enqueue("Hello".getBytes(), attrs);
|
||||
|
||||
runner.run(1);
|
||||
runner.assertTransferCount(InvokeHTTP.REL_SUCCESS_REQ, 1);
|
||||
runner.assertTransferCount(InvokeHTTP.REL_RESPONSE, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchWithEmptyELExpression() throws Exception {
|
||||
addHandler(new MutativeMethodHandler(MutativeMethod.PATCH, InvokeHTTP.DEFAULT_CONTENT_TYPE));
|
||||
|
||||
runner.setProperty(InvokeHTTP.PROP_METHOD, "PATCH");
|
||||
runner.setProperty(InvokeHTTP.PROP_URL, url + "/patch");
|
||||
|
||||
final Map<String, String> attrs = new HashMap<>();
|
||||
attrs.put(CoreAttributes.MIME_TYPE.key(), "");
|
||||
runner.enqueue("Hello".getBytes(), attrs);
|
||||
|
||||
runner.run(1);
|
||||
runner.assertTransferCount(InvokeHTTP.REL_SUCCESS_REQ, 1);
|
||||
runner.assertTransferCount(InvokeHTTP.REL_RESPONSE, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPatchWithContentTypeProperty() throws Exception {
|
||||
final String suppliedMimeType = "text/plain";
|
||||
addHandler(new MutativeMethodHandler(MutativeMethod.PATCH, suppliedMimeType));
|
||||
|
||||
runner.setProperty(InvokeHTTP.PROP_METHOD, "PATCH");
|
||||
runner.setProperty(InvokeHTTP.PROP_URL, url + "/patch");
|
||||
runner.setProperty(InvokeHTTP.PROP_CONTENT_TYPE, suppliedMimeType);
|
||||
|
||||
final Map<String, String> attrs = new HashMap<>();
|
||||
attrs.put(CoreAttributes.MIME_TYPE.key(), "text/csv");
|
||||
runner.enqueue("Hello".getBytes(), attrs);
|
||||
|
||||
runner.run(1);
|
||||
runner.assertTransferCount(InvokeHTTP.REL_SUCCESS_REQ, 1);
|
||||
runner.assertTransferCount(InvokeHTTP.REL_RESPONSE, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelete() throws Exception {
|
||||
addHandler(new DeleteHandler());
|
||||
|
@ -1402,7 +1489,7 @@ public abstract class TestInvokeHttpCommon {
|
|||
}
|
||||
}
|
||||
|
||||
private enum MutativeMethod { POST, PUT }
|
||||
private enum MutativeMethod { POST, PUT, PATCH }
|
||||
|
||||
|
||||
public static class MutativeMethodHandler extends AbstractHandler {
|
||||
|
|
Loading…
Reference in New Issue