OpenApiDocument.SerializeAsV2 throws UriFormatException when given schemes and basePath, but no host
Summary
When Microsoft.OpenAPI.Readers reads an OpenAPI 2.0 document in which the Swagger Object has properties "schemes": [ "http" ] and "basePath": "/api" but does not have a "host" property, it sets OpenApiServer.Url ="http:///api". If OpenApiDocument.SerializeAsV2 is then called, it throws UriFormatException.
OpenAPI Specification Version 2.0 does not require host, regardless of whether schemes is empty.
To reproduce
Console1App.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.OpenApi" Version="1.2.2" />
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.2.2" />
</ItemGroup>
</Project>
Program.cs:
using System.IO;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Readers;
using Microsoft.OpenApi.Writers;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string originalYaml = @"
swagger: '2.0'
info:
title: 'Demo'
version: '1.0'
basePath: '/api'
schemes:
- 'http'
paths:
'/demo':
get:
responses:
'200':
description: 'OK'
";
var openApiReader = new OpenApiStringReader();
OpenApiDocument document = openApiReader.Read(originalYaml, out _);
var openApiWriter = new OpenApiJsonWriter(new StringWriter());
document.SerializeAsV2(openApiWriter); // fails with exception
}
}
}
Expected behaviour
No exception is thrown, and the resulting JSON likewise has basePath and schemes but no host.
Actual behaviour
An exception is thrown:
Unhandled Exception: System.UriFormatException: Invalid URI: The hostname could not be parsed.
at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
at System.Uri..ctor(String uriString, UriKind uriKind)
at Microsoft.OpenApi.Models.OpenApiDocument.WriteHostInfoV2(IOpenApiWriter writer, IList`1 servers) in d:\a\1\s\src\Microsoft.OpenApi\Models\OpenApiDocument.cs:line 263
at Microsoft.OpenApi.Models.OpenApiDocument.SerializeAsV2(IOpenApiWriter writer) in d:\a\1\s\src\Microsoft.OpenApi\Models\OpenApiDocument.cs:line 123
at ConsoleApp1.Program.Main(String[] args) in …\ConsoleApp1\Program.cs:line 32
The stack trace is the same as in https://github.com/microsoft/OpenAPI.NET/issues/440, but the Exception.Message is different.
This is not quite a duplicate of https://github.com/microsoft/OpenAPI.NET/issues/350 because that one does not cover the UriFormatException that is thrown during roundtripping.
I mean, in https://github.com/microsoft/OpenAPI.NET/issues/350, the complaint is that OpenApiServer.Url should be "/v2" rather than "http:///v2". Here, I'd be happy with OpenApiServer.Url being "http:///api" if the library just were able to serialize it back to OpenAPI 2.0.
The OpenAPI 2.0 specification says:
If the host is not included, the host serving the documentation is to be used
However, in your case, the OpenAPI description is not coming from somewhere we can infer a host from.
I don't think it is possible to have a relative reference with no host that includes a scheme. If you really just want a relative reference in the URL, then you will need to drop the scheme. That will give you this:

However, in your case, the OpenAPI description is not coming from somewhere we can infer a host from.
The plan was to use this library to serialize the OpenAPI 2.0 document and place it on an HTTP server, and the host would be implied when the document is later retrieved from that server.
@KalleOlaviNiemitalo So, then the example I showed that just includes the basePath should be sufficient for your scenario. Just don't include the host or scheme and the basePath will be relative to the host the OpenAPI description was found on.