Current section
Files
Jump to
Current section
Files
lib/hermes/uri.ex
defmodule Hermes.URI do
@moduledoc """
URI utilities for handling URL paths consistently.
"""
@doc """
Joins a base URI with a path segment, handling trailing and leading slashes correctly.
## Examples
iex> Hermes.URI.join_path(URI.new!("http://localhost:8000"), "/mcp")
%URI{scheme: "http", host: "localhost", port: 8000, path: "/mcp"}
iex> Hermes.URI.join_path(URI.new!("http://localhost:8000/"), "/mcp")
%URI{scheme: "http", host: "localhost", port: 8000, path: "/mcp"}
iex> Hermes.URI.join_path(URI.new!("http://localhost:8000/api"), "/mcp")
%URI{scheme: "http", host: "localhost", port: 8000, path: "/api/mcp"}
"""
@spec join_path(URI.t(), String.t()) :: URI.t()
def join_path(base_uri, path) when is_binary(path) do
base_path = base_uri.path || ""
segments =
[base_path, path]
|> Enum.map(&String.trim(&1, "/"))
|> Enum.reject(&(&1 == ""))
normalized_path = "/" <> Enum.join(segments, "/")
%{base_uri | path: normalized_path}
end
def join_path(base_uri, nil), do: base_uri
@doc """
Joins a base URI with multiple path segments, handling trailing and leading slashes correctly.
"""
@spec join_paths(URI.t(), [String.t()]) :: URI.t()
def join_paths(base_uri, paths) when is_list(paths) do
base_path = base_uri.path || ""
segments =
[base_path | paths]
|> Enum.map(&String.trim(&1, "/"))
|> Enum.reject(&(&1 == ""))
normalized_path = "/" <> Enum.join(segments, "/")
%{base_uri | path: normalized_path}
end
end