This commit is contained in:
Looly 2022-07-20 13:38:55 +08:00
parent 28fde6ddcf
commit 32235d3b7e
4 changed files with 55 additions and 17 deletions

View File

@ -85,8 +85,7 @@ public class Console {
public static void log(final Throwable t, final String template, final Object... values) {
out.println(StrUtil.format(template, values));
if (null != t) {
//noinspection CallToPrintStackTrace
t.printStackTrace();
t.printStackTrace(out);
out.flush();
}
}

View File

@ -340,6 +340,22 @@ public final class UrlBuilder implements Builder<String> {
return this;
}
/**
* 是否path的末尾加 /
*
* @param withEngTag 是否path的末尾加 /
* @return this
* @since 5.8.5
*/
public UrlBuilder setWithEndTag(final boolean withEngTag) {
if (null == this.path) {
this.path = UrlPath.of();
}
this.path.setWithEndTag(withEngTag);
return this;
}
/**
* 增加路径节点路径节点中的"/"会被转义为"%2F"
*
@ -489,7 +505,7 @@ public final class UrlBuilder implements Builder<String> {
final StringBuilder fileBuilder = new StringBuilder();
// path
fileBuilder.append(StrUtil.blankToDefault(getPathStr(), StrUtil.SLASH));
fileBuilder.append(getPathStr());
// query
final String query = getQueryStr();

View File

@ -22,6 +22,16 @@ public class UrlPath {
private List<String> segments;
private boolean withEngTag;
/**
* 构建UrlPath
*
* @return UrlPath
* @since 6.0.0
*/
public static UrlPath of() {
return new UrlPath();
}
/**
* 构建UrlPath
*
@ -30,9 +40,7 @@ public class UrlPath {
* @return UrlPath
*/
public static UrlPath of(final CharSequence pathStr, final Charset charset) {
final UrlPath urlPath = new UrlPath();
urlPath.parse(pathStr, charset);
return urlPath;
return of().parse(pathStr, charset);
}
/**
@ -100,12 +108,12 @@ public class UrlPath {
public UrlPath parse(CharSequence path, final Charset charset) {
if (StrUtil.isNotEmpty(path)) {
// 原URL中以/结尾则这个规则需保留issue#I1G44J@Gitee
if(StrUtil.endWith(path, CharUtil.SLASH)){
if (StrUtil.endWith(path, CharUtil.SLASH)) {
this.withEngTag = true;
}
path = fixPath(path);
if(StrUtil.isNotEmpty(path)){
if (StrUtil.isNotEmpty(path)) {
final List<String> split = StrUtil.split(path, '/');
for (final String seg : split) {
addInternal(URLDecoder.decodeForPath(seg, charset), false);
@ -135,20 +143,21 @@ public class UrlPath {
* path = path-abempty / path-absolute / path-noscheme / path-rootless / path-empty
* </pre>
*
* @param charset encode编码null表示不做encode
* @param charset encode编码null表示不做encode
* @param encodePercent 是否编码`%`
* @return 如果没有任何内容则返回空字符串""
* @since 5.8.0
*/
public String build(final Charset charset, final boolean encodePercent) {
if (CollUtil.isEmpty(this.segments)) {
return StrUtil.EMPTY;
// 没有节点的path取决于是否末尾追加/如果不追加返回空串否则返回/
return withEngTag ? StrUtil.SLASH : StrUtil.EMPTY;
}
final char[] safeChars = encodePercent ? null : new char[]{'%'};
final StringBuilder builder = new StringBuilder();
for (final String segment : segments) {
if(builder.length() == 0){
if (builder.length() == 0) {
// 根据https://www.ietf.org/rfc/rfc3986.html#section-3.3定义
// path的第一部分不允许有":"其余部分允许
// 在此处的Path部分特指host之后的部分即不包含第一部分
@ -157,12 +166,15 @@ public class UrlPath {
builder.append(CharUtil.SLASH).append(RFC3986.SEGMENT.encode(segment, charset, safeChars));
}
}
if (StrUtil.isEmpty(builder)) {
// 空白追加是保证以/开头
builder.append(CharUtil.SLASH);
}else if (withEngTag && false == StrUtil.endWith(builder, CharUtil.SLASH)) {
// 尾部没有/则追加否则不追加
builder.append(CharUtil.SLASH);
if (withEngTag) {
if (StrUtil.isEmpty(builder)) {
// 空白追加是保证以/开头
builder.append(CharUtil.SLASH);
} else if (false == StrUtil.endWith(builder, CharUtil.SLASH)) {
// 尾部没有/则追加否则不追加
builder.append(CharUtil.SLASH);
}
}
return builder.toString();

View File

@ -20,6 +20,17 @@ public class UrlBuilderTest {
Assert.assertEquals("http://www.hutool.cn/", buildUrl);
}
@Test
public void buildWithoutSlashTest(){
// https://github.com/dromara/hutool/issues/2459
String buildUrl = UrlBuilder.of().setScheme("http").setHost("192.168.1.1").setPort(8080).setWithEndTag(false).build();
Assert.assertEquals("http://192.168.1.1:8080", buildUrl);
buildUrl = UrlBuilder.of().setScheme("http").setHost("192.168.1.1").setPort(8080).addQuery("url", "http://192.168.1.1/test/1")
.setWithEndTag(false).build();
Assert.assertEquals("http://192.168.1.1:8080?url=http://192.168.1.1/test/1", buildUrl);
}
@Test
public void buildTest2() {
// path中的+不做处理