~singpolyma/dhall-ruby

e0a1301bf1cf4da2b2e751048b8c4df2ac019cc6 — Stephen Paul Weber 2 years ago ab6a076
Support headers for HTTP import
3 files changed, 74 insertions(+), 6 deletions(-)

M lib/dhall/ast.rb
M lib/dhall/resolve.rb
M test/test_resolve.rb
M lib/dhall/ast.rb => lib/dhall/ast.rb +33 -1
@@ 261,6 261,11 @@ module Dhall
			with(elements: elements.each_with_index.map(&block))
		end

		def each(&block)
			elements.each(&block)
			self
		end

		def reduce(z)
			elements.reverse.reduce(z) { |acc, x| yield x, acc }
		end


@@ 303,6 308,10 @@ module Dhall
			type.nil? ? self : with(type: type)
		end

		def each
			self
		end

		def reduce(z)
			z
		end


@@ 678,6 687,10 @@ module Dhall
			end
		end

		def to_s
			value
		end

		def as_json
			[18, value]
		end


@@ 720,6 733,11 @@ module Dhall
				fragment  Either(nil, ::String)
			end)

			HeaderType = RecordType.new(record: {
				"header" => Variable["Text"],
				"value"  => Variable["Text"]
			})

			def initialize(headers, authority, *path, query, fragment)
				super(
					headers:   headers,


@@ 730,6 748,16 @@ module Dhall
				)
			end

			def with(hash)
				self.class.new(
					hash.fetch(:headers),
					authority,
					*path,
					query,
					fragment
				)
			end

			def self.from_uri(uri)
				(uri.scheme == "https" ? Https : Http).new(
					nil,


@@ 740,12 768,16 @@ module Dhall
				)
			end

			def headers
				super || EmptyList.new(type: HeaderType)
			end

			def uri
				URI("#{scheme}://#{authority}/#{path.join("/")}?#{query}")
			end

			def as_json
				[headers.as_json, authority, *path, query, fragment]
				[@headers.as_json, authority, *path, query, fragment]
			end
		end


M lib/dhall/resolve.rb => lib/dhall/resolve.rb +24 -4
@@ 21,7 21,17 @@ module Dhall
		ReadHttpSources = lambda do |sources|
			sources.map do |source|
				Promise.resolve(nil).then do
					r = Net::HTTP.get_response(source.uri)
					uri = source.uri
					req = Net::HTTP::Get.new(uri)
					source.headers.each do |header|
						req[header.fetch("header").to_s] = header.fetch("value").to_s
					end
					r = Net::HTTP.start(
						uri.hostname,
						uri.port,
						use_ssl: uri.scheme == "https"
					) { |http| http.request(req) }

					raise ImportFailedException, source if r.code != "200"
					r.body
				end


@@ 128,11 138,21 @@ module Dhall
			end

			def resolve_http(http_source)
				@http_resolutions.register(http_source)
				ExpressionResolver.for(http_source.headers)
					.resolve(self).then do |headers|
					@http_resolutions.register(
						http_source.with(headers: headers.normalize)
					)
				end
			end

			def resolve_https(https_source)
				@https_resolutions.register(https_source)
				ExpressionResolver.for(https_source.headers)
					.resolve(self).then do |headers|
					@https_resolutions.register(
						https_source.with(headers: headers.normalize)
					)
				end
			end

			def finish!


@@ 265,7 285,7 @@ module Dhall
			register_for Object

			def resolve(*)
				@expr
				Promise.resolve(@expr)
			end
		end
	end

M test/test_resolve.rb => test/test_resolve.rb +17 -1
@@ 24,7 24,9 @@ class TestResolve < Minitest::Test
						"self"     => "hRgY9gADZHNlbGY",
						"text"     => "aGFp",
						"moretext" => "hRgY9gEDZHRleHQ",
						"2text"    => "hAMGhRgY9gEDZHRleHSFGBj2AANobW9yZXRleHQ"
						"2text"    => "hAMGhRgY9gEDZHRleHSFGBj2AANobW9yZXRleHQ",
						"using"    => "iRgY9gAAhRgY9gADZ2hlYWRlcnNkZS50ZGF09vY",
						"headers"  => "gwT2ggiiZmhlYWRlcoISYnRoZXZhbHVlghJidHY"
					}.fetch(source.pathname.to_s)))
				end
			end


@@ 173,6 175,20 @@ class TestResolve < Minitest::Test
		assert_equal Dhall::Variable["_"], expr.resolve(@resolver).sync
	end

	def test_headers
		stub_request(:get, "http://e.td/t")
			.with(headers: { "Th" => "tv" })
			.to_return(status: 200, body: "\x00")

		expr = Dhall::Import.new(
			nil,
			Dhall::Import::Expression,
			Dhall::Import::RelativePath.new("using")
		)

		assert_equal Dhall::Variable["_"], expr.resolve(@resolver).sync
	end

	def test_ipfs
		stub_request(:get, "http://localhost:8000/ipfs/TESTCID")
			.to_return(status: 200, body: "\x00")