ASP.Net Core 3.1 Swagger 页面通过 HTTPS 加载,但现在尝试使用 HTTP 并且浏览器请求失败

问题描述

我刚刚将我的项目从 Swashbuckle 5.6.3 升级到 6.0.7。我没有进行任何代码更改,但是现在当尝试使用 Swagger 页面来测试 API 时,Swagger 生成的 URL 没有使用 https,即使该页面是通过 https 加载的,而且我能找到的所有文档都说它应该推断基于用于加载 Swagger 页面的 URL 的方案。

这里是配置代码

        services.AddSwaggerGen(c => {
            c.SwaggerDoc(apiSettings.Version,new OpenApiInfo { Title = apiSettings.Name,Version = apiSettings.Version });

            c.CustomSchemaIds(type => type.FullName);

            c.AddSecurityDeFinition("Bearer",new OpenApiSecurityScheme {
                Description = "JWT Authorization header using the Bearer scheme.",Name        = "Authorization",In          = ParameterLocation.Header,Type        = SecuritySchemeType.ApiKey,Scheme      = "bearer",Reference   = new OpenApiReference { Type = ReferenceType.SecurityScheme,Id = "Bearer" }
            });

            c.AddSecurityRequirement(new OpenApiSecurityRequirement {
                { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme,Id = "Bearer" } },new List<string>() }
            });
        });

和:

        app.UseSwagger();

        app.UseSwaggerUI(c => {
            c.SwaggerEndpoint($"/swagger/{apiSettings.Version}/swagger.json",$"{apiSettings.Name} {apiSettings.Version}");
        });

现在有新的配置设置来指定方案吗?

解决方法

在 6.0.7 版本中,您可以使用 MapSwagger 扩展方法更改此行为。

#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi.hpp>

#include <vector>
#include <tuple>

namespace ascii = boost::spirit::ascii;
namespace qi = boost::spirit::qi;
namespace ql = qi::labels;
namespace ph = boost::phoenix;


struct Struct1
{
  float f;
};
BOOST_FUSION_ADAPT_STRUCT(
    Struct1,(float,f))

struct Struct2
{
  float f;
  int i;
};
BOOST_FUSION_ADAPT_STRUCT(
    Struct2,f)
    (int,i))


template<typename Iterator,typename Result>
class ElementParser : public qi::grammar<Iterator,Result(),ascii::space_type>
{
public:
  using ValueType = Result;
  
  ElementParser() : ElementParser::base_type(element) {}
  
private:
  qi::rule<Iterator,ascii::space_type> element;
};


template<typename Iterator>
class Struct2Tuple : public qi::grammar<Iterator,std::tuple<float,int>(),ascii::space_type>
{
public:
  using ValueType = std::tuple<float,int>;
  
  Struct2Tuple() : Struct2Tuple::base_type(tupleElement)
  {
    ph::function convert = [](auto const& s,auto& t)
    {
      t = std::make_tuple(s.f,s.i);
    };
    
    tupleElement = structElement[convert(ql::_1,qi::_val)];
  }
  
private:
  qi::rule<Iterator,ValueType(),ascii::space_type> tupleElement;
  ElementParser<Iterator,Struct2> structElement;
};


template<typename Iterator,typename ElementParser,typename Element = typename ElementParser::ValueType>
class SP : public qi::grammar<Iterator,std::vector<Element>(),ascii::space_type>
{
private:
  static
  void flattenAndAppend(std::vector<Element>& into,std::vector<std::vector<Element>> const& vector)
  {
    for(auto const& subvector: vector)
    {
      into.insert(into.end(),subvector.begin(),subvector.end());
    }
  }
  
  static
  void flattenAndAppend(std::vector<Element>& into,std::vector<Element> const& vector)
  {
    into.insert(into.end(),vector.begin(),vector.end());
  }
  
public:
  SP()
    : SP::base_type(sequence)
  {
    ph::function append = [](auto& into,auto const& a1)
    {
      flattenAndAppend(into,a1);
    };
    
    sequence = (simpleVector % ',')[append(qi::_val,ql::_1)];
    simpleVector = qi::repeat(1)[simple];
  }
  
private:
  using Rule = qi::rule<Iterator,ascii::space_type>;
  Rule sequence;
  Rule simpleVector;
  ElementParser simple;
};


void sequenceTest()
{
  using Iterator = std::string::const_iterator;
  
  SP<Iterator,qi::uint_parser<>,std::size_t> uintParser;                  // OK
  SP<Iterator,ElementParser<Iterator,float>> floatParser;                 // OK
  SP<Iterator,std::vector<float>>> vectorParser;   // OK
  
  SP<Iterator,Struct2Tuple<Iterator>> struct2tupleParser;                  // OK.
  
  SP<Iterator,float>>> tupleParser;   // now OK
  SP<Iterator,Struct1>> struct1Parser;                  // now OK
  SP<Iterator,Struct2>> struct2Parser;                  // now OK
}
,

最后,这是对我有用的最终代码。

        app.UseEndpoints(endpoints => {
            endpoints.MapControllers();

            endpoints.MapSwagger("/swagger/{documentName}/swagger.json",options => {
                options.PreSerializeFilters.Add((swagger,httpRequest) => { });
            });
        });