首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么RestTemplate不对“+”符号进行urlencode,而对其他所有东西进行urlencode?

为什么RestTemplate不对“+”符号进行urlencode,而对其他所有东西进行urlencode?
EN

Stack Overflow用户
提问于 2019-06-02 23:22:37
回答 1查看 396关注 0票数 0

我发现了一个奇怪的问题,在这个问题中,urlencoding的行为不一致。

更新

Spring版本4.3和5.1之间有差异:

代码语言:javascript
复制
// FAIL in MVC 4.x 
@Test
public void test2() {
    rt.getForObject("http://localhost/expr={expr}", String.class, "x/y");
    Assert.assertEquals("http://localhost/expr=x%2Fy", savedUri.toString());
}

// FAIL in MVC 4 or 5
@Test
public void test3() {
    rt.getForObject("http://localhost/expr={expr}", String.class, "x+y");
    Assert.assertEquals("http://localhost/expr=x%2By", savedUri.toString());
}

// ok in MVC 4.x, FAIL in MVC 5
@Test
public void test4() {
    rt.getForObject("http://localhost/expr={expr}", String.class, "x+y");
    Assert.assertEquals("http://localhost/expr=x+y", savedUri.toString());
}

这可能是Spring更大的参考文献的一部分,因为它也体现在一个完全不同的地方-- 这里

问题详细信息

我的问题最好用下面的独立测试来说明。不要被ClientHttpRequestFactory吓倒--重要的是最后两种测试方法。

代码语言:javascript
复制
package com.stackoverflow.questions;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URI;

import org.apache.commons.io.input.ReaderInputStream;
import org.apache.commons.io.output.WriterOutputStream;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.RestTemplate;

public class RestTemplateTest {

    StringWriter stringWriter = new StringWriter();

    WriterOutputStream writerOutputStream = new WriterOutputStream(stringWriter);

    HttpHeaders headers = new HttpHeaders();

    URI savedUri;

    ClientHttpRequestFactory rf = new ClientHttpRequestFactory() {
        @Override
        public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
            savedUri = uri;
            return new ClientHttpRequest() {
                @Override
                public OutputStream getBody() throws IOException {
                    return writerOutputStream;
                }

                @Override
                public HttpHeaders getHeaders() {
                    return headers;
                }

                @Override
                public URI getURI() {
                    return uri;
                }

                @Override
                public String getMethodValue() {
                    return httpMethod.name();
                }

                @Override
                public ClientHttpResponse execute() throws IOException {

                    writerOutputStream.close();

                    return new ClientHttpResponse() {
                        @Override
                        public HttpHeaders getHeaders() {
                            return new HttpHeaders();
                        }

                        @Override
                        public InputStream getBody() throws IOException {
                            return new ReaderInputStream(new StringReader("test"));
                        }

                        @Override
                        public String getStatusText() throws IOException {
                            return "OK";
                        }

                        @Override
                        public HttpStatus getStatusCode() throws IOException {
                            return HttpStatus.OK;
                        }

                        @Override
                        public int getRawStatusCode() throws IOException {
                            return 200;
                        }

                        @Override
                        public void close() {
                        }
                    };
                }
            };
        }
    };
    RestTemplate rt = new RestTemplate(rf);

    @Test
    public void test1() {
        String resp = rt.getForObject("http://whatever", String.class);
        Assert.assertEquals("test", resp);
    }

    @Test
    public void test2() {
        rt.getForObject("http://localhost/expr={expr}", String.class, "x/y");
        Assert.assertEquals("http://localhost/expr=x%2Fy", savedUri.toString());
    }

    @Test
    public void test3() {
        rt.getForObject("http://localhost/expr={expr}", String.class, "x+y");
        Assert.assertEquals("http://localhost/expr=x%2By", savedUri.toString());
    }

}

发生了什么:

  • 除号/被正确地编码到%2F - test2()传递
  • 加法符号+没有被编码到%2B -它仍然是+和test3()失败

应该发生什么:

test3()应该通过。应该将+编码为%2B,因为+是URL中的一个特殊字符,被许多服务器端web框架解释为空白。

,这里发生了什么,有没有通用的修复?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-03 00:48:27

是否应该对+进行编码存在不确定性。老的RFCs说是的,新的说可能。

尝试按以下方式设置编码模式:

代码语言:javascript
复制
  DefaultUriBuilderFactory builderFactory = new DefaultUriBuilderFactory();
  builderFactory.setEncodingMode(EncodingMode.VALUES_ONLY);
  restTemplate.setUriTemplateHandler(builderFactory);

有关讨论,请参见SPR-19394SPR-20750

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56419684

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档