打开外部 DTD 时出错 - 400 错误

An error has occurred while opening external DTD - 400 Error

提问人:Josh 提问时间:7/21/2023 更新时间:7/21/2023 访问量:24

问:

当我尝试验证 xml 时,我遇到了第三方 dtd 间歇性地抛出 HTTP 状态 400 错误的问题。

抛出的错误是:

打开外部 DTD“http://example.com/fake/path/MyDTD.dtd”时出错:响应状态代码不指示成功:400(错误请求)。
在 System.Xml.XmlTextReaderImpl.Throw (异常 e) 在 System.Xml.XmlTextReaderImpl.PushExternalEntityOrSubset (字符串 publicId、 字符串 systemId、 uri baseUri、 字符串 entityName) 在 System.Xml.XmlTextReaderImpl.DtdParserProxy_PushExternalSubset (字符串 systemId、 字符串 publicId) 在 System.Xml.XmlTextReaderImpl.DtdParserProxy.System.Xml.IDtdParserAdapter.PushExternalSubset (字符串 systemId、 字符串 publicId)



在 System.Xml.DtdParser.ParseExternalSubset() 在 System.Xml.DtdParser.ParseInDocumentDtd (布尔值 saveInternalSubset) 在 System.Xml.DtdParser.Parse (布尔值 saveInternalSubset) 在 System.Xml.DtdParser.System.Xml.IDtdParser.ParseInternalDtd (IDtdParserAdapter 适配器,布尔值 saveInternalSubset) 在 System.Xml.XmlTextReaderImpl.ParseDtd() 在 System.Xml.XmlTextReaderImpl.ParseDoctypeDecl()





在 System.Xml.XmlTextReaderImpl.ParseDocumentContent() 在 System.Xml.XmlTextReaderImpl.Read() 在 System.Xml.XmlValidatingReaderImpl.Read() 在 MyApi.Infrastructure.Serializers.MyCustomXmlSerializer.ValidateAgainstDtd (字符串 xml,布尔值 throwOnFailure)



在 D:\a\1\s\src\Infrastructure\Serializers\MyCustomXmlSerializer.cs:第 198 行

这是我验证xml的方法:

public bool ValidateAgainstDtd(string xml, bool throwOnFailure = false)
{
    var messages = new List<string>();

    try
    {
        var settings = new XmlReaderSettings
        {
            ValidationType = ValidationType.DTD,
            DtdProcessing = DtdProcessing.Parse,
            XmlResolver = new XmlPreloadedResolver(new XmlUrlResolver())
        };

        settings.ValidationEventHandler += (sender, args) => messages.Add(args.Message);

        using var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml));
        using var reader = XmlReader.Create(stream, settings);

        while (reader.Read()) { }  //this is line 198 in the exception
    }
    catch (Exception e)
    {
        messages.Add($"DTD Validation Exception: {e.Message}{Environment.NewLine}{e.StackTrace}");
    }

    if (messages.Count == 0)
    {
        return true;
    }

    if (throwOnFailure)
    {
        throw new CustomXmlSerializationException(messages.ToArray());
    }

    return false;
}

我没有收到任何其他验证错误,并且我们正在序列化的模型在几个不同的调用之间很常见,但它只在一次调用中失败,并且只是间歇性地失败 - 相同的调用在其他一些情况下有效。

在本地开发机器上作为 Nunit 套件的一部分运行的集成测试中,相同的代码工作正常,但是当我们将代码部署到我们的舞台环境中时,我们突然遇到拉回 DTD 的间歇性问题。

C# XML 序列化 DTD

评论

0赞 jdweng 7/21/2023
错误 400 表示服务器未接受您的请求。这意味着您在响应中没有获得有效的 xml。当您获得 400 状态时,不应尝试反序列化 xml。只有在获得 200 ok时才反序列化。间歇性问题是与服务器的连接间歇性失败。
0赞 Josh 7/24/2023
这是我的第一个想法,但与我合作的第三方表示,他们查看了日志,没有看到任何连接失败。我开始怀疑我是否可以在突然涌入的请求中触发 cloudflare(他们的主机)的防御措施。
0赞 jdweng 7/24/2023
服务器可以返回它想要的任何状态(即使它是错误的)。然后,如果连接完成,供应商代码将报告错误错误。或者您的代码将转到其他应用程序。您可能正在通过代理,并且代理正在创建错误。但是,如果您正在通过代理,则日志文件中不会看到任何消息。让供应商检查失败时日志中是否有任何记录。时间很重要。
0赞 Josh 8/3/2023
我使用完全相同的代码进行集成测试,这些代码工作正常。他们验证并获取数据没有问题。但是,当我在代码周围使用 .NET 核心 (6.0) API 时,它在所有环境中都失败了 - 本地和我们的 Azure 环境。
0赞 jdweng 8/3/2023
您的错误是由 xml 文件的内容引起的。您的代码所做的只是读取 xml 文件,所以我同意它不是代码。问题可能出在 xml 文件和/或您正在使用的 Core 版本上。这可能是在更高版本的 Core 6.0 中修复的错误。我会在代码开头声明 XmlReader,然后在异常中放置一个断点。然后,当发生错误时,可以检查 XmlReader 以查看发生异常的行。

答: 暂无答案