forked from loafle/openapi-generator-original
[feign] Use feign-form (#4124)
* [feign] Use feign-form Fix #4108 * [feign] Convert java.util.Date params to rfc3339 with an Expander
This commit is contained in:
committed by
wing328
parent
51b941cf88
commit
901a981f26
@@ -18,6 +18,7 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
|
||||
import feign.Feign;
|
||||
import feign.RequestInterceptor;
|
||||
import feign.form.FormEncoder;
|
||||
import feign.jackson.JacksonDecoder;
|
||||
import feign.jackson.JacksonEncoder;
|
||||
import feign.slf4j.Slf4jLogger;
|
||||
@@ -37,7 +38,7 @@ public class ApiClient {
|
||||
objectMapper = createObjectMapper();
|
||||
apiAuthorizations = new LinkedHashMap<String, RequestInterceptor>();
|
||||
feignBuilder = Feign.builder()
|
||||
.encoder(new FormAwareEncoder(new JacksonEncoder(objectMapper)))
|
||||
.encoder(new FormEncoder(new JacksonEncoder(objectMapper)))
|
||||
.decoder(new JacksonDecoder(objectMapper))
|
||||
.logger(new Slf4jLogger());
|
||||
}
|
||||
|
||||
@@ -1,192 +0,0 @@
|
||||
package {{invokerPackage}};
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URLEncoder;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
|
||||
import java.text.DateFormat;
|
||||
|
||||
import feign.codec.EncodeException;
|
||||
import feign.codec.Encoder;
|
||||
import feign.RequestTemplate;
|
||||
|
||||
{{>generatedAnnotation}}
|
||||
public class FormAwareEncoder implements Encoder {
|
||||
public static final String UTF_8 = "utf-8";
|
||||
private static final String LINE_FEED = "\r\n";
|
||||
private static final String TWO_DASH = "--";
|
||||
private static final String BOUNDARY = "----------------314159265358979323846";
|
||||
|
||||
private byte[] lineFeedBytes;
|
||||
private byte[] boundaryBytes;
|
||||
private byte[] twoDashBytes;
|
||||
private byte[] atBytes;
|
||||
private byte[] eqBytes;
|
||||
|
||||
private final Encoder delegate;
|
||||
private final DateFormat dateFormat;
|
||||
|
||||
public FormAwareEncoder(Encoder delegate) {
|
||||
this.delegate = delegate;
|
||||
this.dateFormat = new RFC3339DateFormat();;
|
||||
|
||||
try {
|
||||
this.lineFeedBytes = LINE_FEED.getBytes(UTF_8);
|
||||
this.boundaryBytes = BOUNDARY.getBytes(UTF_8);
|
||||
this.twoDashBytes = TWO_DASH.getBytes(UTF_8);
|
||||
this.atBytes = "&".getBytes(UTF_8);
|
||||
this.eqBytes = "=".getBytes(UTF_8);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
|
||||
if (object instanceof Map) {
|
||||
try {
|
||||
encodeFormParams(template, (Map<String, Object>) object);
|
||||
} catch (IOException e) {
|
||||
throw new EncodeException("Failed to create request", e);
|
||||
}
|
||||
} else {
|
||||
delegate.encode(object, bodyType, template);
|
||||
}
|
||||
}
|
||||
|
||||
private void encodeFormParams(RequestTemplate template, Map<String, Object> formParams) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
boolean isMultiPart = isMultiPart(formParams);
|
||||
boolean isFirstField = true;
|
||||
for (Map.Entry<String, Object> param : formParams.entrySet()) {
|
||||
String keyStr = param.getKey();
|
||||
if (param.getValue() instanceof File) {
|
||||
addFilePart(baos, keyStr, (File) param.getValue());
|
||||
} else {
|
||||
String valueStr = parameterToString(param.getValue());
|
||||
if (isMultiPart) {
|
||||
addMultiPartFormField(baos, keyStr, valueStr);
|
||||
} else {
|
||||
addEncodedFormField(baos, keyStr, valueStr, isFirstField);
|
||||
isFirstField = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isMultiPart) {
|
||||
baos.write(lineFeedBytes);
|
||||
baos.write(twoDashBytes);
|
||||
baos.write(boundaryBytes);
|
||||
baos.write(twoDashBytes);
|
||||
baos.write(lineFeedBytes);
|
||||
}
|
||||
|
||||
String contentType = isMultiPart ? "multipart/form-data; boundary=" + BOUNDARY : "application/x-www-form-urlencoded";
|
||||
template.header("Content-type");
|
||||
template.header("Content-type", contentType);
|
||||
template.header("MIME-Version", "1.0");
|
||||
template.body(baos.toByteArray(), Charset.forName(UTF_8));
|
||||
}
|
||||
|
||||
/*
|
||||
* Currently only supports text files
|
||||
*/
|
||||
private void addFilePart(ByteArrayOutputStream baos, String fieldName, File uploadFile) throws IOException {
|
||||
String fileName = uploadFile.getName();
|
||||
baos.write(twoDashBytes);
|
||||
baos.write(boundaryBytes);
|
||||
baos.write(lineFeedBytes);
|
||||
|
||||
String contentDisposition = "Content-Disposition: form-data; name=\"" + fieldName
|
||||
+ "\"; filename=\"" + fileName + "\"";
|
||||
baos.write(contentDisposition.getBytes(UTF_8));
|
||||
baos.write(lineFeedBytes);
|
||||
String contentType = "Content-Type: " + URLConnection.guessContentTypeFromName(fileName);
|
||||
baos.write(contentType.getBytes(UTF_8));
|
||||
baos.write(lineFeedBytes);
|
||||
baos.write(lineFeedBytes);
|
||||
|
||||
BufferedReader reader = new BufferedReader(new FileReader(uploadFile));
|
||||
InputStream input = new FileInputStream(uploadFile);
|
||||
byte[] bytes = new byte[4096];
|
||||
int len = bytes.length;
|
||||
while ((len = input.read(bytes)) != -1) {
|
||||
baos.write(bytes, 0, len);
|
||||
baos.write(lineFeedBytes);
|
||||
}
|
||||
|
||||
baos.write(lineFeedBytes);
|
||||
}
|
||||
|
||||
private void addEncodedFormField(ByteArrayOutputStream baos, String name, String value, boolean isFirstField) throws IOException {
|
||||
if (!isFirstField) {
|
||||
baos.write(atBytes);
|
||||
}
|
||||
|
||||
String encodedName = URLEncoder.encode(name, UTF_8);
|
||||
String encodedValue = URLEncoder.encode(value, UTF_8);
|
||||
baos.write(encodedName.getBytes(UTF_8));
|
||||
baos.write("=".getBytes(UTF_8));
|
||||
baos.write(encodedValue.getBytes(UTF_8));
|
||||
}
|
||||
|
||||
private void addMultiPartFormField(ByteArrayOutputStream baos, String name, String value) throws IOException {
|
||||
baos.write(twoDashBytes);
|
||||
baos.write(boundaryBytes);
|
||||
baos.write(lineFeedBytes);
|
||||
|
||||
String contentDisposition = "Content-Disposition: form-data; name=\"" + name + "\"";
|
||||
String contentType = "Content-Type: text/plain; charset=utf-8";
|
||||
|
||||
baos.write(contentDisposition.getBytes(UTF_8));
|
||||
baos.write(lineFeedBytes);
|
||||
baos.write(contentType.getBytes(UTF_8));
|
||||
baos.write(lineFeedBytes);
|
||||
baos.write(lineFeedBytes);
|
||||
baos.write(value.getBytes(UTF_8));
|
||||
baos.write(lineFeedBytes);
|
||||
}
|
||||
|
||||
private boolean isMultiPart(Map<String, Object> formParams) {
|
||||
boolean isMultiPart = false;
|
||||
for (Map.Entry<String, Object> entry : formParams.entrySet()) {
|
||||
if (entry.getValue() instanceof File) {
|
||||
isMultiPart = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isMultiPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the given parameter object into string.
|
||||
*/
|
||||
public String parameterToString(Object param) {
|
||||
if (param == null) {
|
||||
return "";
|
||||
} else if (param instanceof Date) {
|
||||
return formatDate((Date) param);
|
||||
} else if (param instanceof Collection) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
for(Object o : (Collection)param) {
|
||||
if(b.length() > 0) {
|
||||
b.append(",");
|
||||
}
|
||||
b.append(String.valueOf(o));
|
||||
}
|
||||
return b.toString();
|
||||
} else {
|
||||
return String.valueOf(param);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the given Date object into string.
|
||||
*/
|
||||
public String formatDate(Date date) {
|
||||
return dateFormat.format(date);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package {{invokerPackage}};
|
||||
|
||||
import feign.Param;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Param Expander to convert {@link Date} to RFC3339
|
||||
*/
|
||||
public class ParamExpander implements Param.Expander {
|
||||
|
||||
private static final DateFormat dateformat = new RFC3339DateFormat();
|
||||
|
||||
@Override
|
||||
public String expand(Object value) {
|
||||
if (value instanceof Date) {
|
||||
return dateformat.format(value);
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package {{package}};
|
||||
|
||||
import {{invokerPackage}}.ApiClient;
|
||||
{{#legacyDates}}
|
||||
import {{invokerPackage}}.ParamExpander;
|
||||
{{/legacyDates}}
|
||||
|
||||
{{#imports}}import {{import}};
|
||||
{{/imports}}
|
||||
@@ -25,12 +28,12 @@ public interface {{classname}} extends ApiClient.Api {
|
||||
*/
|
||||
@RequestLine("{{httpMethod}} {{{path}}}{{#hasQueryParams}}?{{/hasQueryParams}}{{#queryParams}}{{baseName}}={{=<% %>=}}{<%paramName%>}<%={{ }}=%>{{#hasMore}}&{{/hasMore}}{{/queryParams}}")
|
||||
@Headers({
|
||||
"Content-type: {{vendorExtensions.x-contentType}}",
|
||||
"Content-Type: {{vendorExtensions.x-contentType}}",
|
||||
"Accept: {{vendorExtensions.x-accepts}}",{{#headerParams}}
|
||||
"{{baseName}}: {{=<% %>=}}{<%paramName%>}<%={{ }}=%>"{{#hasMore}},
|
||||
{{/hasMore}}{{/headerParams}}
|
||||
})
|
||||
{{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}@Param("{{paramName}}") {{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
|
||||
{{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{nickname}}({{#allParams}}{{^isBodyParam}}{{^legacyDates}}@Param("{{paramName}}") {{/legacyDates}}{{#legacyDates}}@Param(value="{{paramName}}", expander=ParamExpander.class) {{/legacyDates}}{{/isBodyParam}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ ext {
|
||||
swagger_annotations_version = "1.5.9"
|
||||
jackson_version = "2.7.5"
|
||||
feign_version = "8.17.0"
|
||||
feign_form_version = "2.0.2"
|
||||
junit_version = "4.12"
|
||||
oltu_version = "1.0.1"
|
||||
}
|
||||
@@ -106,6 +107,7 @@ dependencies {
|
||||
compile "com.netflix.feign:feign-core:$feign_version"
|
||||
compile "com.netflix.feign:feign-jackson:$feign_version"
|
||||
compile "com.netflix.feign:feign-slf4j:$feign_version"
|
||||
compile "io.github.openfeign.form:feign-form:$feign_form_version"
|
||||
compile "com.fasterxml.jackson.core:jackson-core:$jackson_version"
|
||||
compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version"
|
||||
compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version"
|
||||
|
||||
@@ -13,6 +13,7 @@ lazy val root = (project in file(".")).
|
||||
"com.netflix.feign" % "feign-core" % "8.16.0" % "compile",
|
||||
"com.netflix.feign" % "feign-jackson" % "8.17.0" % "compile",
|
||||
"com.netflix.feign" % "feign-slf4j" % "8.16.0" % "compile",
|
||||
"io.github.openfeign.form" % "feign-form" % "2.0.2" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-core" % "2.7.5" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-annotations" % "2.7.5" % "compile",
|
||||
"com.fasterxml.jackson.core" % "jackson-databind" % "2.7.5" % "compile",
|
||||
|
||||
@@ -125,6 +125,11 @@
|
||||
<artifactId>feign-slf4j</artifactId>
|
||||
<version>${feign-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign.form</groupId>
|
||||
<artifactId>feign-form</artifactId>
|
||||
<version>${feign-form-version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- JSON processing: jackson -->
|
||||
<dependency>
|
||||
@@ -167,6 +172,7 @@
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<swagger-core-version>1.5.9</swagger-core-version>
|
||||
<feign-version>8.17.0</feign-version>
|
||||
<feign-form-version>2.0.2</feign-form-version>
|
||||
<jackson-version>2.7.5</jackson-version>
|
||||
<junit-version>4.12</junit-version>
|
||||
<maven-plugin-version>1.0.0</maven-plugin-version>
|
||||
|
||||
Reference in New Issue
Block a user