Module: DurableHuggingfaceHub::Utils::Headers

Defined in:
lib/durable_huggingface_hub/utils/headers.rb

Overview

HTTP header building utilities for HuggingFace Hub API requests.

This module provides functions for constructing proper HTTP headers including User-Agent, Authorization, and custom headers.

Class Method Summary collapse

Class Method Details

.build_hf_headers(token: nil, library_name: nil, library_version: nil, user_agent: nil, headers: nil) ⇒ Hash

Builds standard headers for HuggingFace Hub API requests.

Examples:

Basic usage

headers = Headers.build_hf_headers(token: "hf_...")

With custom library info

headers = Headers.build_hf_headers(
  token: "hf_...",
  library_name: "my_app",
  library_version: "1.0.0"
)

Parameters:

  • token (String, nil) (defaults to: nil)

    Authentication token

  • library_name (String, nil) (defaults to: nil)

    Name of the library using this client

  • library_version (String, nil) (defaults to: nil)

    Version of the library

  • user_agent (String, nil) (defaults to: nil)

    Custom user agent string

  • headers (Hash, nil) (defaults to: nil)

    Additional custom headers

Returns:

  • (Hash)

    Complete headers hash

Raises:



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/durable_huggingface_hub/utils/headers.rb', line 31

def self.build_hf_headers(token: nil, library_name: nil, library_version: nil, user_agent: nil, headers: nil)
  # Validate parameters
  if token && !token.is_a?(String)
    raise ValidationError.new("token", "Token must be a string")
  end

  if library_name && !library_name.is_a?(String)
    raise ValidationError.new("library_name", "Library name must be a string")
  end

  if library_version && !library_version.is_a?(String)
    raise ValidationError.new("library_version", "Library version must be a string")
  end

  if user_agent && !user_agent.is_a?(String)
    raise ValidationError.new("user_agent", "User agent must be a string")
  end

  if headers && !headers.is_a?(Hash)
    raise ValidationError.new("headers", "Custom headers must be a hash")
  end

  result = {}

  # User-Agent header
  result["User-Agent"] = build_user_agent(
    library_name: library_name,
    library_version: library_version,
    custom_agent: user_agent
  )

  # Authorization header
  if token
    result["Authorization"] = "Bearer #{token}"
  end

  # Merge custom headers
  if headers
    result.merge!(headers)
  end

  result
end

.build_user_agent(library_name: nil, library_version: nil, custom_agent: nil) ⇒ String

Builds a User-Agent string for HTTP requests.

Format: “[custom] [library/version] huggingface_hub/version; ruby/version”

Examples:

Headers.build_user_agent
# => "huggingface_hub/0.1.0; ruby/3.3.0"

With library info

Headers.build_user_agent(library_name: "transformers", library_version: "4.0.0")
# => "transformers/4.0.0 huggingface_hub/0.1.0; ruby/3.3.0"

Parameters:

  • library_name (String, nil) (defaults to: nil)

    Name of the calling library

  • library_version (String, nil) (defaults to: nil)

    Version of the calling library

  • custom_agent (String, nil) (defaults to: nil)

    Custom user agent to prepend

Returns:

  • (String)

    User-Agent string

Raises:



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/durable_huggingface_hub/utils/headers.rb', line 92

def self.build_user_agent(library_name: nil, library_version: nil, custom_agent: nil)
  # Validate parameters
  if library_name && !library_name.is_a?(String)
    raise ValidationError.new("library_name", "Library name must be a string")
  end

  if library_version && !library_version.is_a?(String)
    raise ValidationError.new("library_version", "Library version must be a string")
  end

  if custom_agent && !custom_agent.is_a?(String)
    raise ValidationError.new("custom_agent", "Custom agent must be a string")
  end

  parts = []

  # Custom agent
  parts << custom_agent if custom_agent

  # Library identification
  if library_name && library_version && !library_version.empty?
    parts << "#{library_name}/#{library_version}"
  elsif library_name && !library_name.empty?
    parts << library_name
  end

  # HuggingFace Hub client identification
  hf_part = "huggingface_hub/#{DurableHuggingfaceHub::VERSION}"

  # Ruby version
  ruby_part = "ruby/#{RUBY_VERSION}"

  # Join library/custom parts with space, then add hf; ruby
  library_part = parts.empty? ? "" : "#{parts.join(" ")} "
  "#{library_part}#{hf_part}; #{ruby_part}"
end

.extract_commit_sha(headers) ⇒ String?

Extracts commit SHA from response headers.

Parameters:

  • headers (Hash)

    Response headers

Returns:

  • (String, nil)

    Commit SHA if present

Raises:



153
154
155
156
157
158
159
160
161
162
# File 'lib/durable_huggingface_hub/utils/headers.rb', line 153

def self.extract_commit_sha(headers)
  if headers && !headers.is_a?(Hash)
    raise ValidationError.new("headers", "Headers must be a hash")
  end

  return nil unless headers

  headers[Constants::HEADER_X_REPO_COMMIT] ||
    headers[Constants::HEADER_X_REPO_COMMIT.downcase]
end

.extract_etag(headers) ⇒ String?

Extracts ETag from response headers.

Parameters:

  • headers (Hash)

    Response headers

Returns:

  • (String, nil)

    ETag value (with quotes removed)

Raises:



169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/durable_huggingface_hub/utils/headers.rb', line 169

def self.extract_etag(headers)
  if headers && !headers.is_a?(Hash)
    raise ValidationError.new("headers", "Headers must be a hash")
  end

  return nil unless headers

  etag = headers["ETag"] || headers["etag"]
  return nil unless etag

  # Remove surrounding quotes if present
  etag.gsub(/^"|"$/, "")
end

.extract_linked_size(headers) ⇒ Integer?

Extracts linked file size from response headers.

Parameters:

  • headers (Hash)

    Response headers

Returns:

  • (Integer, nil)

    File size in bytes

Raises:



188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/durable_huggingface_hub/utils/headers.rb', line 188

def self.extract_linked_size(headers)
  if headers && !headers.is_a?(Hash)
    raise ValidationError.new("headers", "Headers must be a hash")
  end

  return nil unless headers

  size = headers[Constants::HEADER_X_LINKED_SIZE] ||
         headers[Constants::HEADER_X_LINKED_SIZE.downcase]

  size&.to_i
end

.extract_request_id(headers) ⇒ String?

Extracts request ID from response headers.

Parameters:

  • headers (Hash)

    Response headers

Returns:

  • (String, nil)

    Request ID if present

Raises:



134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/durable_huggingface_hub/utils/headers.rb', line 134

def self.extract_request_id(headers)
  if headers && !headers.is_a?(Hash)
    raise ValidationError.new("headers", "Headers must be a hash")
  end

  return nil unless headers

  # Try common header names
  headers["X-Request-Id"] ||
    headers["x-request-id"] ||
    headers["Request-Id"] ||
    headers["request-id"]
end

.lfs_file?(headers) ⇒ Boolean

Checks if response indicates the file is stored in LFS.

Parameters:

  • headers (Hash)

    Response headers

Returns:

  • (Boolean)

    True if file is in LFS

Raises:



206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/durable_huggingface_hub/utils/headers.rb', line 206

def self.lfs_file?(headers)
  if headers && !headers.is_a?(Hash)
    raise ValidationError.new("headers", "Headers must be a hash")
  end

  return false unless headers

  etag = headers[Constants::HEADER_X_LINKED_ETAG] ||
         headers[Constants::HEADER_X_LINKED_ETAG.downcase]

  !etag.nil?
end