File: hypertext-references.md

package info (click to toggle)
ruby-protocol-http 0.59.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 864 kB
  • sloc: ruby: 7,612; makefile: 4
file content (140 lines) | stat: -rw-r--r-- 4,127 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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
128
129
130
131
132
133
134
135
136
137
138
139
140
# Hypertext References

This guide explains how to use `Protocol::HTTP::Reference` for constructing and manipulating hypertext references (URLs with parameters).

## Overview

{ruby Protocol::HTTP::Reference} is used to construct "hypertext references" which consist of a path and URL-encoded parameters. References provide a rich API for URL construction, path manipulation, and parameter handling.

## Basic Construction

``` ruby
require "protocol/http/reference"

# Simple reference with parameters:
reference = Protocol::HTTP::Reference.new("/search", nil, nil, {q: "kittens", limit: 10})
reference.to_s
# => "/search?q=kittens&limit=10"

# Parse existing URLs:
reference = Protocol::HTTP::Reference.parse("/api/users?page=2&sort=name#results")
reference.path       # => "/api/users"
reference.query      # => "page=2&sort=name"
reference.fragment   # => "results"

# To get parameters as a hash, decode the query string:
parameters = Protocol::HTTP::URL.decode(reference.query)
parameters           # => {"page" => "2", "sort" => "name"}
```

## Path Manipulation

References support sophisticated path manipulation including relative path resolution:

``` ruby
base = Protocol::HTTP::Reference.new("/api/v1/users")

# Append paths:
user_detail = base.with(path: "123")
user_detail.to_s  # => "/api/v1/users/123"

# Relative path navigation:
parent = user_detail.with(path: "../groups", pop: true)
parent.to_s  # => "/api/v1/groups"

# Absolute path replacement:
root = user_detail.with(path: "/status")
root.to_s  # => "/status"
```

## Advanced Parameter Handling

``` ruby
# Complex parameter structures:
reference = Protocol::HTTP::Reference.new("/search", nil, nil, {
	filters: {
		category: "books", 
		price: {min: 10, max: 50}
	},
	tags: ["fiction", "mystery"]
})

reference.to_s
# => "/search?filters[category]=books&filters[price][min]=10&filters[price][max]=50&tags[]=fiction&tags[]=mystery"

# Parameter merging:
base = Protocol::HTTP::Reference.new("/api", nil, nil, {version: "v1", format: "json"})
extended = base.with(parameters: {detailed: true}, merge: true)
extended.to_s
# => "/api?version=v1&format=json&detailed=true"

# Parameter replacement (using merge: false):
replaced = base.with(parameters: {format: "xml"}, merge: false)
replaced.to_s
# => "/api?format=xml"
```

## Merge Behavior and Query Strings

The `merge` parameter controls both parameter handling and query string behavior:

``` ruby
# Create a reference with both query string and parameters:
ref = Protocol::HTTP::Reference.new("/api", "existing=query", nil, {version: "v1"})
ref.to_s
# => "/api?existing=query&version=v1"

# merge: true (default) - keeps existing query string:
merged = ref.with(parameters: {new: "argument"}, merge: true)
merged.to_s
# => "/api?existing=query&version=v1&new=argument"

# merge: false with new parameters - clears query string:
replaced = ref.with(parameters: {new: "argument"}, merge: false)
replaced.to_s
# => "/api?new=argument"

# merge: false without new parameters - keeps everything:
unchanged = ref.with(path: "v2", merge: false)
unchanged.to_s
# => "/api/v2?existing=query&version=v1"
```

## URL Encoding and Special Characters

References handle URL encoding automatically:

``` ruby
# Spaces and special characters:
reference = Protocol::HTTP::Reference.new("/search", nil, nil, {
	q: "hello world",
	filter: "price > $10"
})
reference.to_s
# => "/search?q=hello%20world&filter=price%20%3E%20%2410"

# Unicode support:
unicode_ref = Protocol::HTTP::Reference.new("/files", nil, nil, {
	name: "résumé.pdf",
	emoji: "😀"
})
unicode_ref.to_s
# => "/files?name=r%C3%A9sum%C3%A9.pdf&emoji=%F0%9F%98%80"
```

## Reference Merging

References can be merged following RFC2396 URI resolution rules:

``` ruby
base = Protocol::HTTP::Reference.new("/docs/guide/")
relative = Protocol::HTTP::Reference.new("../api/reference.html")

merged = base + relative
merged.to_s  # => "/docs/api/reference.html"

# Absolute references override completely
absolute = Protocol::HTTP::Reference.new("/completely/different/path")
result = base + absolute
result.to_s  # => "/completely/different/path"
```