private static String urlEncodeKeyValuePair(Map.Entry<String, String> entry) { try { return URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8.toString()) + '=' + URLEncoder.encode(String.valueOf(entry.getValue()), StandardCharsets.UTF_8.toString()); } catch (UnsupportedEncodingException ex) { throw new EncodeException("Error occurred while URL encoding message", ex); } }
private String urlEncodeKeyValuePair(Map.Entry<String, Object> entry) { try { return URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8.toString()) + '=' + URLEncoder.encode(String.valueOf(entry.getValue()), StandardCharsets.UTF_8.toString()); } catch (UnsupportedEncodingException ex) { throw new EncodeException("Error occurred while URL encoding message", ex); } } }
private String urlEncodeKeyValuePair(Map.Entry<String, Object> entry) { try { return URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8.toString()) + '=' + URLEncoder.encode(String.valueOf(entry.getValue()), StandardCharsets.UTF_8.toString()); } catch (UnsupportedEncodingException ex) { throw new EncodeException("Error occurred while URL encoding message", ex); } } }
/** * Converts objects to an appropriate representation in the template. * * @param object what to encode as the request body. * @param bodyType the type the object should be encoded as. {@code Map<String, ?>}, if form * encoding. * @param template the request template to populate. * @throws feign.codec.EncodeException when encoding failed due to a checked exception. */ @Override public void encode(final Object object, final Type bodyType, final RequestTemplate template) throws EncodeException { try { template.body(mapper.writeValueAsString(object)); } catch (JsonProcessingException e) { throw new EncodeException(e.getMessage(), e); } } }
@Override public void encode(Object object, Type bodyType, RequestTemplate template) { try { JavaType javaType = mapper.getTypeFactory().constructType(bodyType); template.body(writerWithType(javaType).writeValueAsString(object)); } catch (JsonProcessingException e) { throw new EncodeException(e.getMessage(), e); } }
@Override public void encode(Object object, Type bodyType, RequestTemplate template) { try { JavaType javaType = mapper.getTypeFactory().constructType(bodyType); template.body(mapper.writerFor(javaType).writeValueAsString(object)); } catch (JsonProcessingException e) { throw new EncodeException(e.getMessage(), e); } } }
@Override public void encode(Object object, Type bodyType, RequestTemplate template) { if (bodyType == String.class) { template.body(object.toString()); } else if (bodyType == byte[].class) { template.body((byte[]) object, null); } else if (object != null) { throw new EncodeException( format("%s is not a type supported by this encoder.", object.getClass())); } } }
/** * Wraps a single {@link MultipartFile} into a {@link HttpEntity} and sets the * {@code Content-type} header to {@code application/octet-stream} * * @param file * @return */ private HttpEntity<?> encodeMultipartFile(MultipartFile file) { HttpHeaders filePartHeaders = new HttpHeaders(); filePartHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); try { Resource multipartFileResource = new MultipartFileResource(file.getOriginalFilename(), file.getSize(), file.getInputStream()); return new HttpEntity<>(multipartFileResource, filePartHeaders); } catch (IOException ex) { throw new EncodeException("Cannot encode request.", ex); } }
@Override protected RequestTemplate resolve(Object[] argv, RequestTemplate mutable, Map<String, Object> variables) { Map<String, Object> formVariables = new LinkedHashMap<String, Object>(); for (Entry<String, Object> entry : variables.entrySet()) { if (metadata.formParams().contains(entry.getKey())) { formVariables.put(entry.getKey(), entry.getValue()); } } try { encoder.encode(formVariables, Encoder.MAP_STRING_WILDCARD, mutable); } catch (EncodeException e) { throw e; } catch (RuntimeException e) { throw new EncodeException(e.getMessage(), e); } return super.resolve(argv, mutable, variables); } }
@Override protected void write (Output output, String key, Object value) throws EncodeException { val file = (File) value; writeFileMetadata(output, key, file.getName(), null); InputStream input = null; try { input = new FileInputStream(file); val buf = new byte[1024]; int length = input.read(buf); while (length > 0) { output.write(buf, 0, length); length = input.read(buf); } } catch (IOException ex) { val message = String.format("Writing file's '%s' content error", file.getName()); throw new EncodeException(message, ex); } finally { if (input != null) { try { input.close(); } catch (IOException ex) { log.error("Closing file '{}' error", file.getName(), ex); } } } } }
@Override public void encode(Object object, Type bodyType, RequestTemplate template) { if (!(bodyType instanceof Class)) { throw new UnsupportedOperationException( "JAXB only supports encoding raw types. Found " + bodyType); } try { Marshaller marshaller = jaxbContextFactory.createMarshaller((Class) bodyType); StringWriter stringWriter = new StringWriter(); marshaller.marshal(object, stringWriter); template.body(stringWriter.toString()); } catch (JAXBException e) { throw new EncodeException(e.toString(), e); } } }
@Override protected RequestTemplate resolve( final Object[] argv, final RequestTemplate mutable, final Map<String, Object> variables) { final Map<String, Object> formVariables = new HashMap<>(); for (final Map.Entry<String, Object> entry : variables.entrySet()) { if (metadata.formParams().contains(entry.getKey())) { formVariables.put(entry.getKey(), entry.getValue()); } } try { encoder.encode(formVariables, Encoder.MAP_STRING_WILDCARD, mutable); } catch (final EncodeException encodeException) { throw encodeException; } catch (final RuntimeException unexpectedException) { throw new EncodeException(unexpectedException.getMessage(), unexpectedException); } return super.resolve(argv, mutable, variables); } }
/** * Fills the request map with {@link HttpEntity}s containing the given {@link MultipartFile}s. * Sets the {@code Content-type} header to {@code application/octet-stream} for each file. * * @param the current request map. * @param name the name of the array field in the multipart form. * @param files */ private void encodeMultipartFiles(LinkedMultiValueMap<String, Object> map, String name, List<? extends MultipartFile> files) { HttpHeaders filePartHeaders = new HttpHeaders(); filePartHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM); try { for (MultipartFile file : files) { Resource multipartFileResource = new MultipartFileResource(file.getOriginalFilename(), file.getSize(), file.getInputStream()); map.add(name, new HttpEntity<>(multipartFileResource, filePartHeaders)); } } catch (IOException ex) { throw new EncodeException("Cannot encode request.", ex); } }
@Override protected void write (Output output, String key, Object value) throws EncodeException { val file = (MultipartFile) value; writeFileMetadata(output, key, file.getOriginalFilename(), file.getContentType()); byte[] bytes; try { bytes = file.getBytes(); } catch (IOException ex) { throw new EncodeException("Getting multipart file's content bytes error", ex); } output.write(bytes); } }
@Override public void process (RequestTemplate template, Charset charset, Map<String, Object> data) throws EncodeException { val boundary = Long.toHexString(System.currentTimeMillis()); val output = new Output(charset); for (val entry : data.entrySet()) { val writer = findApplicableWriter(entry.getValue()); writer.write(output, boundary, entry.getKey(), entry.getValue()); } output.write("--").write(boundary).write("--").write(CRLF); val contentTypeHeaderValue = new StringBuilder() .append(getSupportedContentType().getHeader()) .append("; charset=").append(charset.name()) .append("; boundary=").append(boundary) .toString(); template.header(CONTENT_TYPE_HEADER, Collections.<String>emptyList()); // reset header template.header(CONTENT_TYPE_HEADER, contentTypeHeaderValue); // Feign's clients try to determine binary/string content by charset presence // so, I set it to null (in spite of availability charset) for backward compatibility. val bytes = output.toByteArray(); val body = Request.Body.encoded(bytes, null); template.body(body); try { output.close(); } catch (IOException ex) { throw new EncodeException("Output closing error", ex); } }
/** * Encodes the request as a multipart form. It can detect a single {@link MultipartFile}, an * array of {@link MultipartFile}s, or POJOs (that are converted to JSON). * * @param formMap * @param template * @throws EncodeException */ private void encodeMultipartFormRequest(Map<String, ?> formMap, RequestTemplate template) throws EncodeException { if (formMap == null) { throw new EncodeException("Cannot encode request with null form."); } LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>(); for (Entry<String, ?> entry : formMap.entrySet()) { Object value = entry.getValue(); if (isMultipartFile(value)) { map.add(entry.getKey(), encodeMultipartFile((MultipartFile) value)); } else if (isMultipartFileArray(value)) { encodeMultipartFiles(map, entry.getKey(), Arrays.asList((MultipartFile[]) value)); } else { map.add(entry.getKey(), encodeJsonObject(value)); } } encodeRequest(map, multipartHeaders, template); }
@Override public void encode(Object requestBody, Type bodyType, RequestTemplate request) throws EncodeException { Class<?> requestType = requestBody.getClass(); if (AnnotationUtils.findAnnotation(requestType, RaptorMessage.class) != null) { if ("GET".equalsIgnoreCase(request.method())) { try { Map<String, String> map = RaptorMessageUtils.transferMessageToMap(requestBody); for (Map.Entry<String, String> entry : map.entrySet()) { request.query(entry.getKey(), entry.getValue()); } } catch (Exception e) { throw new RuntimeException("Transfer requestBody to query string error.", e); } } else { FeignRequestOutputMessage outputMessage = new FeignRequestOutputMessage(request); try { raptorMessageConverter.write(requestBody, MediaType.APPLICATION_JSON, outputMessage); request.body(outputMessage.body(), StandardCharsets.UTF_8); } catch (IOException ex) { throw new EncodeException("Error converting request body", ex); } request.headers(HttpHeadersUtils.getHeaders(outputMessage.getHeaders())); } } else { throw new RuntimeException("Can't encode requestBody, bodyType must be RaptorMessage."); } } }
@Override protected RequestTemplate resolve(Object[] argv, RequestTemplate mutable, Map<String, Object> variables) { Object body = argv[metadata.bodyIndex()]; checkArgument(body != null, "Body parameter %s was null", metadata.bodyIndex()); try { encoder.encode(body, metadata.bodyType(), mutable); } catch (EncodeException e) { throw e; } catch (RuntimeException e) { throw new EncodeException(e.getMessage(), e); } return super.resolve(argv, mutable, variables); } }
throw new EncodeException("Cannot encode request.", ex);
@Override protected RequestTemplate resolve( final Object[] argv, final RequestTemplate mutable, final Map<String, Object> variables) { final Object body = argv[metadata.bodyIndex()]; checkNotNull(body, "Body parameter %s was null", metadata.bodyIndex()); try { encoder.encode(body, metadata.bodyType(), mutable); } catch (final EncodeException encodeException) { throw encodeException; } catch (final RuntimeException unexpectedException) { throw new EncodeException(unexpectedException.getMessage(), unexpectedException); } return super.resolve(argv, mutable, variables); } }