Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是'*';根据HTTP规范,内容类型的有效通配符?_Java_Http_Jax Rs_Http Accept Header - Fatal编程技术网

Java 是'*';根据HTTP规范,内容类型的有效通配符?

Java 是'*';根据HTTP规范,内容类型的有效通配符?,java,http,jax-rs,http-accept-header,Java,Http,Jax Rs,Http Accept Header,我们使用的是Jax-RS的Jersey参考实现。Jersey的Jax-RS客户端实现在没有指定accept头的情况下向请求附加一个默认accept头。默认的accept标头如下所示: Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 如您所见,它使用单个星号“*”作为内容类型(在image/jpeg之后) 在Jax-RS规范(请参阅)中,此单个*定义为 /** * The value of a type or subt

我们使用的是Jax-RS的Jersey参考实现。Jersey的Jax-RS客户端实现在没有指定accept头的情况下向请求附加一个默认accept头。默认的accept标头如下所示:

Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 
如您所见,它使用单个星号“*”作为内容类型(在image/jpeg之后)

在Jax-RS规范(请参阅)中,此单个*定义为

/**
 * The value of a type or subtype wildcard {@value #MEDIA_TYPE_WILDCARD}.
 */
public static final String MEDIA_TYPE_WILDCARD = "*";
/**
 * A {@code String} constant representing wildcard {@value #WILDCARD} media type .
 */
public final static String WILDCARD = "*/*";
我将其解释为“任何媒体类型的通配符”

“*/*”定义为

/**
 * The value of a type or subtype wildcard {@value #MEDIA_TYPE_WILDCARD}.
 */
public static final String MEDIA_TYPE_WILDCARD = "*";
/**
 * A {@code String} constant representing wildcard {@value #WILDCARD} media type .
 */
public final static String WILDCARD = "*/*";
我将其解释为“任何媒体范围的通配符”

但是,HTTP规范()未提及“任何媒体类型”通配符,仅提及媒体范围通配符:

media-range    = ( "*/*"
                 / ( type "/" "*" )
                 / ( type "/" subtype )
                 ) *( OWS ";" OWS parameter )

(..)

The asterisk "*" character is used to group media types into ranges,
with "*/*" indicating all media types and "type/*" indicating all
subtypes of that type.  The media-range can include media type
parameters that are applicable to that range.
我将其解释为允许的内容类型:

  • */*
  • 正文/*
  • 文本/纯文本
换句话说,内容类型必须始终采用“某物斜杠某物”或“单个*不是有效的内容类型”的形式。尽管如此,后者并未明确说明

现在这两个规范都是公开标准化的,HTTP规范在某种程度上是Jax-RS规范的父文档,因为Jax-RS是基于HTTP的。IMHO两个标准在通配符内容类型方面相互矛盾

问题是,什么是适用的

  • 单个星号“*”是否为有效的内容类型(允许服务器响应任何内容类型)
  • 或者使用单个星号是否会产生错误?如果是,是哪一个?
    • 400坏请求
    • 406不可接受
  • 或者服务器应该更宽容一些,将*视为通配符*/*,尽管*不是有效的内容类型(并且可能会在日志或其他内容中产生警告)
编辑 在处理Jsoup(而不是JaxRS/Jersey)时,我观察到Jsoup使用的是相同的默认接受类型,而且似乎默认头是
sun.net.www.protocol.http.HttpURLConnection

static final String acceptString = "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2";
所以,如果这是一个bug,它不是Jersey的bug,而是Java的HttpURLConnection

我将其解释为“任何媒体类型的通配符”

我认为这是不正确的。它是类型或子类型的通配符。任何媒体类型的通配符都定义为
*/*
,就像在HTTP规范中一样


另外,如果有疑问,请遵循HTTP规范。最后,这就是您正在使用的通信协议。另一方可能不知道Jax RS规范。

Jersey客户端库/代码似乎有问题

查看以下位置的JAX-RS规范:

,我找不到任何支持媒体类型*的明确提及。它明确提及支持的媒体类型,如“n/m”,其中m可以是*或n和m可以是*,但仅*未提及

引用文件:

首先,让我们定义客户端媒体类型和服务器媒体类型 如请求中的Accept标头和@Products所示 资源方法上的注释。让客户端媒体类型 形式为n/m;q=v1,服务器媒体类型为n/m;qs=v2 以及形式为n/m;q=v1;qs=v2;d=v3的组合媒体类型,其中 下面定义了距离系数d。对于这些类型中的任何一种,m都可以是 ∗, 或者m和n可以是∗ 假设q和qs的值为 1.0如果缺席

因此,我认为Jersey客户端API有问题,它在没有提供明确的Accept头时创建默认Accept头,并将其值设置为您提到的值,即

Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 
另外,仅在此添加JAX-RS规范,其中提到:

(a) Filter M by removing members that do not meet the following criteria:
• The request method is supported. If no methods support the request method an implementation
MUST generate a NotAllowedException (405 status) and no entity. Note the
additional support for HEAD and OPTIONS described in Section 3.3.5.
• The media type of the request entity body (if any) is a supported input data format (see Section
3.5). If no methods support the media type of the request entity body an implementation
MUST generate a NotSupportedException (415 status) and no entity.
• At least one of the acceptable response entity body media types is a supported output data
format (see Section 3.5). If no methods support one of the acceptable response entity body
media types an implementation MUST generate a NotAcceptableException (406 status)
and no entity
因此,如果请求的媒体类型(在Accept标头中)不能与任何服务器支持的方法的响应媒体类型匹配,406 HTTP代码将是合适的


但是,在您的情况下,请求中指定了各种媒体类型,包括支持所有媒体类型的通用类型,因此抛出错误不是正确的做法,即使*不是完全正确的媒体类型。

所以您说,jax rs规范是不正确的(因为它使用*作为内容类型的通配符)?@GeraldMücke是的,看起来是这样。另一方面,接下来,您可能希望接受来自客户端的
*
,并将其解释为
*/*
。JAX-RS中的意图是不同的。它是目标端的匹配。这只是为了匹配传入的请求-它具有一个具体的媒体类型,例如applicationn/json-到服务端点。如果服务端点具有例如@products(“/json”),则将使用该服务端点。具有@products(“*/xml”)的服务端点显然不会。具有@products(“)的服务端点将匹配每个请求的接受。问题是,jersey客户端将请求中的*通配符内容类型发送到服务器,如果服务器端不是基于Jax-RS的rest服务怎么办?@GeraldMücke嗯,这当然取决于服务器。我怀疑这会产生严重的问题,但您必须进行彻底的测试。我认为,当您说“Jersey的Jax RS客户端实现在请求中附加了默认的accept头”时,了解您所指的是哪一个客户端是很重要的。您能澄清一下吗?我使用Jersey参考实现创建并使用了一个Jax-RS客户机。当我没有指定accept标头时,Jersey会设置默认标头(请参见此处),抛出的错误为IMHO ok,因为请求标头字段格式不正确…@JulianReschke这会使其具有限制性,并可能成为报告程序的阻止程序,因为他还指向另一个链接,其中提到开发人员很难删除默认的Accept头。此外,正如上面巴特所指出的,稳健性是这里要考虑的一个好主意:理解。我只是想指出,根据规范,这是可以的。还要记住,剧烈的错误处理有助于保持协议干净,而不会出现严重的互操作问题。请参阅XML或HTTP/2.Update