问题描述
我刚刚将我的项目从 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) => { });
});
});