MultipartContent.java
/**
* Copyright (C) 2017 HttpBuilder-NG Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package groovyx.net.http;
import groovy.lang.Closure;
import groovy.lang.DelegatesTo;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
import static java.util.Collections.unmodifiableList;
import static groovyx.net.http.util.Misc.randomString;
/**
* Multipart request content object used to define the multipart data. An example would be:
*
* [source,groovy]
* ----
* request.contentType = 'multipart/form-data'
* request.body = multipart {
* field 'userid','someuser'
* part 'icon', 'user-icon.jpg', 'image/jpeg', imageFile
* }
* ----
*
* which would define a `multipart/form-data` request with a field part and a file part with the specified properties.
*/
public class MultipartContent {
private final List<MultipartPart> entries = new LinkedList<>();
private final String boundary = randomString(16);
/**
* Configures multipart request content using a Groovy closure (delegated to {@link MultipartContent}).
*
* @param closure the configuration closure
* @return a configured instance of {@link MultipartContent}
*/
public static MultipartContent multipart(@DelegatesTo(MultipartContent.class) Closure closure) {
MultipartContent content = new MultipartContent();
closure.setDelegate(content);
closure.call();
return content;
}
/**
* Configures multipart request content using a {@link Consumer} which will have an instance of {@link MultipartContent} passed into it for
* configuring the multipart content data.
*
* @param config the configuration {@link Consumer}
* @return a configured instance of {@link MultipartContent}
*/
public static MultipartContent multipart(final Consumer<MultipartContent> config) {
MultipartContent content = new MultipartContent();
config.accept(content);
return content;
}
/**
* Configures a field part with the given field name and value.
*
* @param fieldName the field name
* @param value the value
* @return a reference to this {@link MultipartContent} instance
*/
public MultipartContent field(String fieldName, String value) {
return part(fieldName, value);
}
/**
* Configures a field part with the given field name and value (of the specified content type).
*
* @param fieldName the field name
* @param contentType the value content type
* @param value the value
* @return a reference to this {@link MultipartContent} instance
*/
public MultipartContent field(String fieldName, String contentType, String value) {
return part(fieldName, contentType, value);
}
/**
* Configures a field part with the given field name and value.
*
* @param fieldName the field name
* @param value the value
* @return a reference to this {@link MultipartContent} instance
*/
public MultipartContent part(String fieldName, String value) {
return part(fieldName, null, ContentTypes.TEXT.getAt(0), value);
}
/**
* Configures a field part with the given field name and value (of the specified content type).
*
* @param fieldName the field name
* @param contentType the value content type
* @param value the value
* @return a reference to this {@link MultipartContent} instance
*/
public MultipartContent part(String fieldName, String contentType, String value) {
return part(fieldName, null, contentType, value);
}
/**
* Configures a file part with the specified properties. Encoders must be configured on the {@link HttpBuilder} to handle the content type
* of each configured part.
*
* @param fieldName the field name
* @param fileName the file name
* @param contentType the part content type
* @param content the part content (encoders must be configured)
* @return a reference to this {@link MultipartContent} instance
*/
public MultipartContent part(String fieldName, String fileName, String contentType, Object content) {
entries.add(new MultipartPart(fieldName, fileName, contentType, content));
return this;
}
/**
* Iterates over the configured parts.
*
* @return an {@link Iterable} view of the configured parts.
*/
Iterable<MultipartPart> parts() {
return unmodifiableList(entries);
}
/**
* Used to retrieve the multipart content boundary used by this content. Encoders may provide their own boundary implementation or use
* the one provided by this method.
*
* @return a multipart boundary string for this content.
*/
String boundary() {
return boundary;
}
/**
* Represents a single multipart part.
*/
static class MultipartPart {
private final String fieldName;
private final String fileName;
private final String contentType;
private final Object content;
private MultipartPart(String fieldName, String fileName, String contentType, Object content) {
this.fieldName = fieldName;
this.fileName = fileName;
this.contentType = contentType != null ? contentType : ContentTypes.TEXT.getAt(0);
this.content = content;
}
public String getFieldName() {
return fieldName;
}
public String getFileName() {
return fileName;
}
public String getContentType() {
return contentType;
}
public Object getContent() {
return content;
}
}
}