Feign: upgrade spring-cloud-release from F to G, feign urlencode error

Created on 19 Jan 2019  路  7Comments  路  Source: OpenFeign/feign

upgrade spring-cloud-release from F to G, feign urlencode error

my app server code is

 @PostMapping(value = "/user/userinfo")
    public BaseResult userInfoSignatureCheck(
            @NotBlank @RequestHeader(WxConstants.HN_APP_ID) String hnAppId,
            @NotBlank @RequestParam(WxConstants.SESSION_KEY) String sessionKey,
            @NotBlank @RequestParam String rawData,
            @NotBlank @RequestParam String signature,
            @NotBlank @RequestParam String encryptedData,
            @NotBlank @RequestParam String iv) {
        try {
            ...
            return BaseResult.success(userInfo);
        } catch (WxErrorException e) {
            log.error("WxErrorException", e);
            return BaseResult.fail(e.getError().getErrorCode(), e.getError().getErrorMsg());
        }
    }

and app client code is

@FeignClient(name = "mini-program-api")
public interface MiniProgramApi {

    @RequestMapping(value = "/mini-program-api/user/userinfo", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    BaseResult<Map<String,Object>> userinfo2(@RequestHeader("hn-app-id") String hnAppId,
                                             @RequestParam("sessionKey") String sessionKey,
                                             @RequestParam("rawData") String rawData,
                                             @RequestParam("signature") String signature,
                                             @RequestParam("encryptedData") String encryptedData,
                                             @RequestParam("iv") String iv);

in spring-cloud-release F version
and i request sessionKey param is aaa+bbb
i check okhttp3 request log , sessionKey param has been change to aaa%2B%bbb
and app server accept sessionKey param is aaa+bbb

in spring-cloud-release G version
and i request sessionKey param is aaa+bbb
i check okhttp3 request log , sessionKey param has been change to aaa+bbb (no encode)
and app server accept sessionKey param is aaa bbb

how can i solve this problem?

thanks

bug regression spring-cloud

Most helpful comment

PR #882 is now open. This PR attempts to correct this issue by making sure that each segment of the uri, be it the path or query, are correctly encoded based on the URI and URI Template specifications. With regards to the + symbol, when this appears on the query string, it will be encoded as %2B.

If your intention is to use + as a space, you must use the space character or encode it yourself as %20.

If you are interested in more detail about where all this comes from, I invite you to look at RFC 3986 - Appendix A. It describes what characters are acceptable on each segment of the uri.

All 7 comments

We've also experienced this.

One thing that is not clear to me is that it would appear that not all URL encoding of params have stopped after upgrading from finchley.SR2 to greenwich.release, some characters still are.

using finchley before the + char appears to have been converted to %2B which , I thought was desirable, https://tools.ietf.org/html/rfc3986 (section 2.2. Reserved Characters) .

Using Greenwich, the + is now a literal +, but certain other characters (if present in the input string) are still encoded, e.g. ABC+&? -> ABC+%26%3F. Before (Finchley.SR2) this was ABC%2B%26%3F.

I can use java.net.URLEncoder#encode(java.lang.String, java.lang.String) prior to calling the feign client to encode any params values which might contain reserved characters but it's not clear to me whether it is advisable to do so in terms of the intended behaviour of feign (i.e. it feels like feign does take care of this for at least some chars ?, &).

For the time being, I've modified my calling code to first URL encode any strings with potential for reserved characters before calling feign

I'm looking into this. It appears that we are not applying path and query encoding correctly.

i create a new RequestInterceptor to encode all query param to solve this problem.

@Bean
  public RequestInterceptor feignRequestInterceptor() {
    return template -> {
      if (urlEncode) {
        template.queries().forEach((k, v) -> {
          template.query(k, Lists.newArrayList());
          template.query(k, v.stream().map(l -> URLEncoder.encode(l, StandardCharsets.UTF_8)).collect(
                  Collectors.toList()));
        });
        log.info("url is {}, urlEncode is {}", template.url(), urlEncode);
      }
    };
  }

i hope feign official can solve this problem next version, thanks

I would caution blindly encoding this way. Only some of the encoding is incorrect and your approach will double encode if a value is handled correctly.

And one more important note, URLEncoder does not apply url encoding, it is used to encode form parameters and will incorrectly encode certain values. Use with caution.

@kdavisk6 thanks!

PR #882 is now open. This PR attempts to correct this issue by making sure that each segment of the uri, be it the path or query, are correctly encoded based on the URI and URI Template specifications. With regards to the + symbol, when this appears on the query string, it will be encoded as %2B.

If your intention is to use + as a space, you must use the space character or encode it yourself as %20.

If you are interested in more detail about where all this comes from, I invite you to look at RFC 3986 - Appendix A. It describes what characters are acceptable on each segment of the uri.

Was this page helpful?
0 / 5 - 0 ratings