Given an Openapi definition like
paths:
/foo:
get:
parameters:
- name: ids
in: query
style: form
explode: true
schema:
type: array
items:
$ref: ../components/schemas/id.yml
uniqueItems: true
json_schemer will raise an UnknownRef error when attempting to validate ids. This is because no ref_resolver is provided and thus its default proc { |uri| raise UnknownRef, uri.to_s } is used. This is happening because build_parameter_schema creates a JSONSchemer.schema inline instead of using the new RefResolver module recently introduced by openapi_first. I believe the same thing is also happening for response headers, because build_responses uses a similar approach for the headers schema. I haven't been able to prove this, though.
Not sure how easy it would be to get those using the same technique used for request bodies and response bodies. Still trying to understand how all of this magic is working 😆.
For now, I was able to workaround this by JSONSchemer.configureing a ref_resolver that would be used as a fallback when openapi_first doesn't provide its own.
JSONSchemer.configure do |config|
config.ref_resolver =
JSONSchemer::CachedResolver.new do |uri|
OpenapiFirst::FileLoader.load(
File.join(File.dirname(schema_path), uri.path),
)
end
end
Since that workaround solved my problem, at made me then wonder: instead of creating a new JSONSchemer::CachedResolver for each schema, can we just have a single one that is used by all of them? The current implementation is
def schema(options = {})
ref_resolver = JSONSchemer::CachedResolver.new do |uri|
FileLoader.load(uri.path)
end
base_uri = URI::File.build({ path: "#{dir}/" })
root = JSONSchemer::Schema.new(context, base_uri:, ref_resolver:, **options)
JSONSchemer::Schema.new(value, nil, root, base_uri:, **options)
end
The ref_resolver will be initialized for each schema, which means that each schema is getting its own file cache, and so the same sub schema can be loaded multiple times if it has multiple $refs to it from various parent schemas. I imagine the same ref_resolver could be used for all schemas since there is only a single implementation of it, and the uri.path should still be accurate because the schema has a base_uri provided to it. This might help with performance and memory, because it would be able to re-use any cached schemas across the entire Openapi definition.
Given an Openapi definition like
json_schemerwill raise anUnknownReferror when attempting to validateids. This is because noref_resolveris provided and thus its defaultproc { |uri| raise UnknownRef, uri.to_s }is used. This is happening becausebuild_parameter_schemacreates aJSONSchemer.schemainline instead of using the newRefResolvermodule recently introduced byopenapi_first. I believe the same thing is also happening for response headers, becausebuild_responsesuses a similar approach for theheadersschema. I haven't been able to prove this, though.Not sure how easy it would be to get those using the same technique used for request bodies and response bodies. Still trying to understand how all of this magic is working 😆.
For now, I was able to workaround this by
JSONSchemer.configureing aref_resolverthat would be used as a fallback whenopenapi_firstdoesn't provide its own.Since that workaround solved my problem, at made me then wonder: instead of creating a new
JSONSchemer::CachedResolverfor each schema, can we just have a single one that is used by all of them? The current implementation isThe
ref_resolverwill be initialized for each schema, which means that each schema is getting its own file cache, and so the same sub schema can be loaded multiple times if it has multiple$refs to it from various parent schemas. I imagine the sameref_resolvercould be used for all schemas since there is only a single implementation of it, and theuri.pathshould still be accurate because the schema has abase_uriprovided to it. This might help with performance and memory, because it would be able to re-use any cached schemas across the entire Openapi definition.