WEB / WEB-06.01
URL anatomy and resource addressing
Separate URL components, resource identity, representations, and access decisions. Follow query multiplicity, encoding, and fragment boundaries in native parser results.
1. Core · Mechanism
Read every scenario without motion
Absolute URL
- Input is unparsed
The catalogue address is only text; there is no parsed result or request.
- Address text
- Input: catalogue URL
- Local URL parser
- Parser: pending
- Application view
- View: pending
- Authority is parsed
Scheme, hostname, and explicit port were separated locally. No DNS ran.
- Address text
- Input: unchanged
- Local URL parser
- https: / books.example / 8443
- Application view
- View: pending
- Path/query/fragment are separated
The query contains two tag values; #summary remains a fragment.
- Address text
- Input: unchanged
- Local URL parser
- /catalog/atlas; tags: network, web; #summary
- Application view
- View: pending
- A request-target candidate is prepared
The path/query candidate excludes the fragment. This calculation sends no HTTP.
- Address text
- Input: unchanged
- Local URL parser
- Parser: success
- Application view
- Target: /catalog/atlas?lang=tr&tag=network&tag=web
- Fragment remains in the client view
Summary is a candidate client selection, with no network or scrolling evidence.
- Address text
- Input: unchanged
- Local URL parser
- Parser: success
- Application view
- Fragment: summary; network: not run
No base
- A relative reference exists
/catalog/atlas does not carry a host on its own.
- Address text
- /catalog/atlas
- Local URL parser
- Base: absent
- Application view
- Result: pending
- Constructor is called without a base
The native URL constructor requires a base for this relative input.
- Address text
- /catalog/atlas
- Local URL parser
- Parse: failure / TypeError
- Application view
- Result: pending
- No success result is produced
The exception is not a network failure; no valid absolute result exists.
- Address text
- /catalog/atlas
- Local URL parser
- TypeError retained
- Application view
- Destination: absent
- Context must be supplied separately
Supplying a base starts a new local resolution; it does not rewrite the failed operation.
- Address text
- /catalog/atlas
- Local URL parser
- Base required
- Application view
- HTTP: not sent
ACTORS · STATE · DATA FLOW
Separate the resource from its address
Duru opens Atlas in a book catalogue. The resource is the application’s conceptual entity; the URL is an identifier addressing it. The server can offer an HTML or JSON representation of that entity. Reading an address does not establish the returned bytes, existence, or Duru’s permission.
RFC 3986 presents URI as the general identification framework and URL as a category associated with location or an access mechanism. The modern browser API is named URL; WHATWG specifies interoperable browser parsing. Generic RFC syntax and browser parsing are not identical algorithms for every edge case.
Parsing is local text processing, distinct from DNS, transport, TLS, or sending an HTTP request. books.example is an educational name and is never contacted by this scene.
Read a URL by its components
Read https://books.example:8443/catalog/atlas?lang=tr&tag=network&tag=web#summary as scheme, authority with host/port, path, query, and fragment. Component delimiters matter; splitting everything on slashes is insufficient.
The artifact records protocol, hostname, host, port, pathname, search, and hash from new URL(input). protocol includes its colon, search begins with ?, and hash begins with #. Distinguish the URL record concept from the getter’s serialized representation.
hostname is books.example; host includes :8443. The path is /catalog/atlas, the query contains three pairs, and the fragment identifies summary. These are parser observations, not an HTTP request or server routing decision.
What does the scheme select?
The scheme selects how an address is interpreted. http and https address web resources; other schemes such as mailto do not promise the same transport or path structure. A valid URL does not universally imply an HTTP GET.
An https string expresses intended HTTPS use. Successful parsing has not validated a certificate or established a secure connection; TLS has its own handshake and validation boundaries.
An application accepting only HTTPS resource links applies its scheme policy to the parsed result. Syntax validity and suitability for an application are separate decisions, neither of which proves network success.
Host and port are separate from the path
The authority’s host identifies a target and can use a domain name or an IP address form. DNS resolves domain names; a parser producing hostname has not obtained a DNS answer or proved that a server exists.
The numeric port contributes to selecting a service endpoint. This fixture explicitly chooses 8443; that number is not a universal secure alternative to HTTPS. A listener and its protocol behavior require separate evidence.
HTTPS has default port 443. Parsing https://books.example:443/catalog removes the default port from serialization, and the port getter returns an empty string. The service has not become portless. Non-default 8443 remains and changes origin comparisons.
host can include a port while hostname does not. For logs and configuration, use the components produced by a consistent parser rather than searching the raw string for familiar text.
A path is an application address
/catalog/atlas is the hierarchical path following the authority. Its segments may be inputs to an application’s route contract. They need not correspond to a catalogue directory and an atlas file on the server: a handler can produce a database-backed response.
The server or framework gives the path its application meaning; the URL parser does not know the route table. Case or a trailing slash can select a different resource, a redirect, or the same route according to that contract. No filesystem result is implied here.
The query is not part of pathname. For /catalog/atlas?lang=tr, routing, locale selection, and cache-key construction are subsequent operations with explicit rules.
Read query pairs without losing multiplicity
The query starts with ?. Its business meaning is application-defined. Key/value pairs separated by & are a common form representation handled by URLSearchParams; allowed keys and values still need application rules.
This example repeats tag. get("tag") returns the first value, network, while getAll("tag") preserves network and web. Code assuming a single value can silently lose the second label. Multiplicity belongs to the schema contract rather than being resolved by syntax alone.
Do not hand the entire URL string to URLSearchParams as if it were a query. Use a URL object’s searchParams or the separated search text. lang=tr is a locale candidate, not evidence of object ownership or identity.
Where does the fragment stay?
#summary is a fragment. It is excluded from the target of a normal HTTP resource request and can guide the client to a part of the representation. The derived origin-form path/query is /catalog/atlas?lang=tr&tag=network&tag=web, without #summary.
Client-side handling does not make a fragment a secret vault. Page code can read it and send it in a separate request. The narrower claim is that the initial URL’s fragment component is not included in its ordinary resource request.
The scene prepares a path/query candidate while keeping the fragment separate. It does not send HTTP or execute scrolling; derivation and fragment consumption remain distinct local operations.
Encoding represents data for transport
Percent-encoding represents a byte using % and two hexadecimal digits. Converting Unicode text to bytes first requires an encoding. URLSearchParams uses UTF-8 and form serialization: the fixture’s q value notlar ı becomes q=notlar+%C4%B1.
In form query serialization a space becomes +; a literal plus is preserved as %2B. A plus does not universally mean a space in every URL component. URL.search and URLSearchParams can serialize the same values differently, so identify the layer being observed.
Encoding is not encryption or authorization: the decoded value remains application input. Treating already encoded text as a raw value changes its representation on another encoding pass. Keep parsing and validation order explicit.
The artifact contains small normal-text native API round trips, with no custom server decoding pipeline or parser-bypass model.
Absolute addresses and relative references
An absolute URL supplies its own scheme and required parsing context. A relative reference such as /catalog/atlas cannot identify its host without a base. new URL("/catalog/atlas") throws TypeError; a valid HTTPS base makes resolution possible.
Resolution is not string concatenation. The base path’s last slash, root-relative versus directory-relative form, and query/fragment references affect the result. WEB-06.03 follows those calculations separately.
After parsing, inspect the resulting absolute URL’s components again. Reachability and suitability for the application remain separate from resolution, naming, and permission.
2. Red · Trust & Impact
Read every scenario without motion
Query values
- The normal catalog reference was selected
Duru selects the Atlas catalog link at books.example on port 8443. Its query contains lang=tr and two tag values; #summary is a separate fragment. The consumer retains each component’s purpose.
- URL reference evidence
- Atlas URL / query + fragment
- Structured parsing
- No parsed fields
- Consumer boundary
- No application policy
- Parser fields were separated
The parser separates hostname books.example, host books.example:8443 and pathname /catalog/atlas, producing origin https://books.example:8443. Text similarity does not replace structured hostname or origin comparison.
- URL reference evidence
- Atlas URL / query + fragment
- Structured parsing
- hostname / host / origin separate
- Consumer boundary
- No application policy
- Representation loss was stopped before a decision
tags=[network, web] contains two values. Selecting the first is a different application-schema decision that ignores the second; the parser is not claimed to have collapsed them.
- URL reference evidence
- Atlas URL / query + fragment
- Structured parsing
- hostname / host / origin separate
- Consumer boundary
- Both tags retained: network,web
- Encoding is not authority
Value A+B becomes q=A%2BB under form encoding; notlar ı becomes q=notlar+%C4%B1. The conversion creates neither encryption nor permission, only another representation.
- URL reference evidence
- Raw values / form serialization separate
- Structured parsing
- hostname / host / origin separate
- Consumer boundary
- Both tags retained: network,web
- Parser success is not policy success
After creating a structured URL, the application separately evaluates permitted scheme/destination/port and query schema. Resource authorization does not follow from URL anatomy.
- URL reference evidence
- Raw values / form serialization separate
- Structured parsing
- Parsed URL / policy still separate
- Consumer boundary
- Both tags retained: network,web
- The boundary result stayed supported
Query multiplicity and first/all-value distinctions are retained. NetworkRequestsExecuted=0 prevents adding a server-interpretation or data-exposure outcome.
- URL reference evidence
- Raw values / form serialization separate
- Structured parsing
- Parsed URL / policy still separate
- Consumer boundary
- Multiplicity preserved / server unknown
Fragment boundary
- The normal catalog reference was selected
Duru selects the Atlas catalog link at books.example on port 8443. Its query contains lang=tr and two tag values; #summary is a separate fragment. The consumer retains each component’s purpose.
- URL reference evidence
- Atlas URL / query + fragment
- Structured parsing
- No parsed fields
- Consumer boundary
- No application policy
- Parser fields were separated
The parser separates hostname books.example, host books.example:8443 and pathname /catalog/atlas, producing origin https://books.example:8443. Text similarity does not replace structured hostname or origin comparison.
- URL reference evidence
- Atlas URL / query + fragment
- Structured parsing
- hostname / host / origin separate
- Consumer boundary
- No application policy
- Representation loss was stopped before a decision
HTTP origin-form contains only /catalog/atlas?lang=tr&tag=network&tag=web. #summary is excluded from that request target and stays client-side. The server router is not claimed to receive the fragment.
- URL reference evidence
- Atlas URL / query + fragment
- Structured parsing
- hostname / host / origin separate
- Consumer boundary
- Request target excludes #summary
- Encoding is not authority
Value A+B becomes q=A%2BB under form encoding; notlar ı becomes q=notlar+%C4%B1. The conversion creates neither encryption nor permission, only another representation.
- URL reference evidence
- Raw values / form serialization separate
- Structured parsing
- hostname / host / origin separate
- Consumer boundary
- Request target excludes #summary
- Parser success is not policy success
After creating a structured URL, the application separately evaluates permitted scheme/destination/port and query schema. Resource authorization does not follow from URL anatomy.
- URL reference evidence
- Raw values / form serialization separate
- Structured parsing
- Parsed URL / policy still separate
- Consumer boundary
- Request target excludes #summary
- The boundary result stayed supported
The fragment stays client-side and request-target covers path/query. This separation measures neither UI scrolling nor actual HTTP delivery.
- URL reference evidence
- Raw values / form serialization separate
- Structured parsing
- Parsed URL / policy still separate
- Consumer boundary
- Fragment separated / delivery unknown
ASSUMPTION · BOUNDARY · CONTROL
Identify the operation that establishes trust
Start a security review by identifying the consumer: browser parser, server router, or application validation. An address can serve different purposes. Familiar-looking text is not a substitute for parsed components or a policy decision.
Follow Duru’s ordinary catalogue link through the artifact. Local scheme, hostname, and port candidates exist before resource authorization. Ask which structured value the next layer trusts and for what purpose.
Place the artifact’s tags array, first get result, and candidate request target side by side. network and web are separate query values; summary is not one of them. Explain why the second tag survives and where the fragment remains on the client.
Representation loss can lose a decision input
Keeping one of two tags or mistaking a fragment for the request target produces a misleading interpretation. Record the reference, parsed components, and schema result as separate observations.
The two tag query pairs and #summary fragment belong to different consumers. The URL parser separates their fields; the application schema decides which query values to use. Excluding the fragment from the request target is not a confidentiality control that prevents client code from sending it in a separate message.
Compare raw A+B with serialized q=A%2BB in the encoding branch. They are two representations of an ordinary value, not a new permission or an encrypted secret. A successful round trip verifies the selected API transformation, not an entire server input pipeline.
3. Blue · Secure development & defense
Read every scenario without motion
Encoding check
- Raw query values were selected
Two ordinary values are selected for form serialization: A+B and notlar ı. These are raw inputs for URLSearchParams, not query strings. Interpret plus and percent text only after identifying the API representation that produced it.
- URL input evidence
- Raw: A+B / notlar ı
- Normalization review
- No serialization yet
- Observation scope
- No server observation
- Form serialization applies its own rules
URLSearchParams represents literal + as %2B, space as +, and the UTF-8 bytes for ı as %C4%B1. This example yields q=A%2BB and q=notlar+%C4%B1. Raw input and the serialized query are different text forms.
- URL input evidence
- Raw: A+B / notlar ı
- Normalization review
- q=A%2BB / q=notlar+%C4%B1
- Observation scope
- No server observation
- Encoding was matched to its source value
q=A%2BB preserves a literal plus; q=notlar+%C4%B1 represents a space and UTF-8 ı. Round-trip reconstructs the value without verifying an entire server pipeline.
- URL input evidence
- A+B ↔ q=A%2BB
- Normalization review
- q=A%2BB / q=notlar+%C4%B1
- Observation scope
- No claim scope
- Query multiplicity stayed in regression
lang and two tag values are read separately; tags expects [network, web]. Fragment summary is not a query key/value and is excluded from HTTP origin-form.
- URL input evidence
- A+B ↔ q=A%2BB
- Normalization review
- Two tags / fragment excluded
- Observation scope
- No claim scope
- Observation retained only necessary data
The catalog URL carries public locale/tag data. Real URLs can spread into history/log/telemetry, so scheme/host/path and needed schema fields are purpose-limited; URLs are not default persistent identity records.
- URL input evidence
- A+B ↔ q=A%2BB
- Normalization review
- Two tags / fragment excluded
- Observation scope
- Public fields / purpose-limited log
- Parser evidence did not replace network evidence
Selected form round-trip and query multiplicity agree. Encoding establishes neither secrecy, input trust nor server acceptance.
- URL input evidence
- A+B ↔ q=A%2BB
- Normalization review
- Two tags / fragment excluded
- Observation scope
- Round-trip consistent / trust separate
Default port
- A URL with an explicit default port was selected
The input is https://books.example:443/catalog. Its raw reference contains :443; href, hostname, port and origin getters are not yet read. Parsing is local here; there is no connection to the service.
- URL input evidence
- Raw https://books.example:443/catalog
- Normalization review
- Getter results pending
- Observation scope
- Network unmeasured
- The default port leaves serialization
Because 443 is HTTPS’s default port, the native URL API returns an empty port getter and href=https://books.example/catalog. The service port has not vanished from this normalized representation; the scheme’s default still applies.
- URL input evidence
- Raw :443 retained for comparison
- Normalization review
- port=""; href=https://books.example/catalog
- Observation scope
- Network unmeasured
- The origin names the same default endpoint
In this HTTP(S) example, origin is https://books.example. Path /catalog is not part of that origin. Explicit :443 and an implicit HTTPS default are different raw texts producing the same normalized origin.
- URL input evidence
- Raw :443 / normalized HTTPS URL
- Normalization review
- Origin https://books.example; default 443
- Observation scope
- Origin equality is not access permission
- A non-default port is a separate comparison
The main catalogue input uses port 8443, which remains in serialization and produces origin https://books.example:8443. Comparing 443 with 8443 explains port normalization, not TLS or listener success.
- URL input evidence
- Comparison: default 443 / non-default 8443
- Normalization review
- 443 empty getter / 8443 retained
- Observation scope
- No TLS/listener outcome
- The observation is produced by the URL API
Href and getters are parsing outputs of the local URL API. Application scheme/port policy, DNS, TLS and HTTP outcomes come from different operations. Substituting parser output for them would report a computed address as an observed connection.
- URL input evidence
- Input and normalized output retained together
- Normalization review
- Producer: local URL API
- Observation scope
- Coverage limited to parsing
- An empty getter does not mean a portless service
The default and non-default comparisons preserve their representation context. A separate relative parse without a base throws TypeError; successful default-port output is not copied into that failure. Network and permission outcomes remain unknown.
- URL input evidence
- Default/non-default/base requirement separate
- Normalization review
- Default port normalized; TypeError separate
- Observation scope
- Parser scope known; access unknown
IMPLEMENTATION · SECURITY CONTROL · VERIFICATION
Use a consistent parser and explicit application policy
Use a standard parser, then evaluate application requirements such as allowed schemes, destinations, or ports against its structured output. Parsing success is not an allow decision, and query schema validation remains separate.
Keep raw input, normalized address, and policy results distinguishable in configuration and observations. Record parser acceptance and application acceptance separately; add network success only when measured.
Preserve data boundaries when logging and creating links
Avoid unnecessary secrets or personal data in queries: addresses can appear in logs, history, and telemetry. This fixture contains only public catalogue labels. Select necessary logging fields rather than treating every full URL as a persistent identity record.
Build links with URL and URLSearchParams, then verify the expected pathname, parameter multiplicity, and fragment separation using benign fixtures. Encoding should not be labeled a security control.
Keep the default-port case separate in lab observations. If a colleague mistakes the empty port getter for an absent service port, show the normalized href with its scheme. Fixing the representation used for logs or configuration helps interpret two text forms of the same destination correctly.
NOW APPLY IT TO THE CASE
Which consumer decisions involve query values, fragments and normalized ports?
Duru uses two tags in the Atlas catalog link. Fragment summary stays client-side while the server target contains path and query. URL parsing or encoding does not grant access to the destination.
Identify the case’s browser and API through URL components. Target, origin and site answer different questions; identify which decision uses each one.
Open the related case file ↗READ THE EXAMPLE TOGETHER
URL component and serialization ledger
Select a field and examine what it supports and where the evidence ends.
Read the raw artifact and field explanations
{
"input": "https://books.example:8443/catalog/atlas?lang=tr&tag=network&tag=web#summary",
"expected": {
"protocol": "https:",
"hostname": "books.example",
"host": "books.example:8443",
"port": "8443",
"pathname": "/catalog/atlas",
"search": "?lang=tr&tag=network&tag=web",
"hash": "#summary",
"origin": "https://books.example:8443",
"tags": [
"network",
"web"
],
"httpOriginForm": "/catalog/atlas?lang=tr&tag=network&tag=web"
},
"defaultPort": {
"input": "https://books.example:443/catalog",
"expectedPort": "",
"expectedHref": "https://books.example/catalog"
},
"formEncoding": [
{
"value": "notlar ı",
"expected": "q=notlar+%C4%B1"
},
{
"value": "A+B",
"expected": "q=A%2BB"
}
],
"relativeWithoutBase": {
"input": "/catalog/atlas",
"expectedError": "TypeError"
},
"networkRequestsExecuted": 0
}- input
- Ordinary catalogue address parsed locally.
- expected.host / expected.hostname
- host includes the port; hostname excludes it.
- expected.tags
- getAll preserves repeated query values.
- expected.httpOriginForm
- Path/query candidate excluding the fragment; no actual request.
- formEncoding
- Form serialization and return to the raw value.
Synthetic inputs checked with the native Node URL API. No DNS, HTTP, TLS, DOM navigation, or server decoding executes.
Two reality checks
A parsed HTTPS address has a secure connection.
Parsing is local; DNS, TLS validation, and HTTP outcomes require separate evidence.
Encoding provides secrecy; fragments belong to the server-bound query.
Encoding is representation. An ordinary request target carries path/query; the fragment remains separate on the client.
YOUR TURN
Work through this story.
Predict the outcome, find the evidence boundary, and explain it in your own words.
What information is lost if tag=network&tag=web is read as one value?
- The two distinct tag values and their order are lost.
- The second tag is a syntax error and must be discarded.
Read the explained answer
The two distinct tag values and their order are lost. — The fixture gives tags=[network, web]; repeating a query key is a valid data structure.
Why does the HTTP origin-form omit #summary?
Selected lesson artifact fields; teaching example
- expected.host
- books.example:8443
- expected.hostname
- books.example
- expected.hash
- #summary
- expected.httpOriginForm
- /catalog/atlas?lang=tr&tag=network&tag=web
- The fragment is a browser-side reference; the selected HTTP target is path+query.
- The fragment belongs to pathname and is sent as a server route.
Read the explained answer
The fragment is a browser-side reference; the selected HTTP target is path+query. — hash is a URL component; it is absent from this origin-form sent to the server.
Explain the form-encoding difference between A+B and notlar ı; why is percent encoding not encryption?
Read the explained answer
URLSearchParams form serialization represents space as +, literal plus as %2B, and ı as UTF-8 bytes %C4%B1. This is reversible representation syntax, providing neither a secret key nor confidentiality. A raw URL string should not be assumed to mean the same thing in different parsers/contexts.
□ I distinguished plus and space serialization.
□ I inferred no confidentiality from encoding.
Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples
MANUAL LAB
URL Boundary Lab
Predict components, origin/site comparisons, and relative resolution before comparing native API output.
Open the prediction → observation → explanation workbook ↗Source on GitHub ↗Sources and scope
- WHATWG — URL StandardGoals · 4.1 URLs · 4.2 URL miscellaneous: default port · 4.4 URL parsing · 4.7 Origin · 6.1 URL class
- RFC 3986 — URI Generic Syntax1.1.3 URI, URL, and URN · 2.1 Percent-Encoding · 2.4 When to Encode or Decode · 3 Syntax Components · 5.2 Relative Resolution
- MDN — URI authoritySyntax · Description: host and port
- MDN — URI schemesSyntax · Description
- MDN — URI pathSyntax · Description
- MDN — URI querySyntax · Description
- MDN — URI fragmentDescription: client processing; fragment not sent in request
- MDN — URLSearchParamsDuplicate search parameters · No URL parsing · Percent encoding · Preserving plus signs · Interaction with URL.searchParams
- MDN — URL constructorSyntax · Parameters · Exceptions