Chapter 13Lesson 02~155 minutes

HTTP Fundamentals and Invoke-WebRequest

Learn HTTP from the protocol up: URIs, methods, headers, status codes, bodies, TLS, redirects, timeouts, response objects, and safe downloads with Invoke-WebRequest.

BeginnerHTTPInvoke-WebRequestTLS

Learning objectives

  • Explain HTTP request/response structure and common status-code families.
  • Break a URI into its meaningful components.
  • Inspect Invoke-WebRequest response objects, headers, content, and links.
  • Use connection/operation timeouts and intentional error handling.
  • Explain TLS/certificate validation and why disabling it is unsafe.
  • Save and validate a download in a disposable workspace.

1. HTTP is an application protocol carried over a transport connection

HTTP defines how a client sends a request and how a server returns a response. HTTPS is HTTP protected by TLS. By the time Invoke-WebRequest receives an HTTP response, DNS, routing, TCP, and usually TLS have already succeeded.

Request/response partMeaning
MethodThe requested action, such as GET or POST.
URIThe resource identifier: scheme, host, port, path, query, and optional fragment.
HeadersMetadata such as accepted media types, authentication, caching, or correlation IDs.
Status codeA three-digit application-level result such as 200, 404, or 503.
BodyOptional request or response content.
Content-TypeDescribes the media type of the body, such as text/html or application/json.

2. Read a URI as structured data, not an opaque string

$uri = [uri]'https://example.com:443/docs/index.html?lang=en#install'
[pscustomobject]@{
    Scheme   = $uri.Scheme
    Host     = $uri.Host
    Port     = $uri.Port
    Path     = $uri.AbsolutePath
    Query    = $uri.Query
    Fragment = $uri.Fragment
}

The fragment is normally interpreted by the client and is not sent as an HTTP request target to the server. Query strings are sent and should be encoded when values contain reserved characters.

3. Methods and status codes are part of the contract

RangeMeaningExamples
1xxInformationalProtocol progress
2xxSuccessful processing200 OK, 201 Created, 204 No Content
3xxRedirection301/302 redirects, 304 Not Modified
4xxClient/request problem400 Bad Request, 401 Unauthorized, 404 Not Found, 429 Too Many Requests
5xxServer-side failure500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable

A status code is not the same thing as transport reachability. TCP can succeed perfectly and the application can still return 503.

4. Invoke-WebRequest returns a response object

Invoke-WebRequest is useful when you care about the HTTP response itself—status, headers, raw content, or HTML links. It returns a BasicHtmlWebResponseObject in modern PowerShell.

$response = Invoke-WebRequest -Uri 'https://example.com/' `
    -ConnectionTimeoutSeconds 5 -OperationTimeoutSeconds 15

$response | Select-Object StatusCode,StatusDescription,RawContentLength
$response.Headers
$response.Content.Substring(0, [math]::Min(120, $response.Content.Length))
$response.Links | Select-Object -First 5 href,outerHTML

5. Headers describe both request intent and response metadata

Headers are key/value metadata. A client might send Accept, User-Agent, or a correlation identifier. A server might return Content-Type, caching policy, rate-limit metadata, or redirect location.

$headers = @{
    Accept = 'text/html'
    'X-Correlation-Id' = [guid]::NewGuid().Guid
}
$response = Invoke-WebRequest -Uri 'https://example.com/' -Headers $headers
$response.Headers['Content-Type']

6. TLS protects the connection and authenticates the server

TLS encrypts traffic and validates the server certificate against trusted authorities and hostname rules. A certificate error is a security signal, not an inconvenience to suppress. PowerShell has -SkipCertificateCheck for controlled testing, but production automation should fix trust/certificate configuration instead of disabling validation.

Proxies can also sit between the client and server. PowerShell 7 uses platform/.NET proxy behavior and supports explicit proxy parameters; this chapter keeps proxy configuration conceptual unless your environment requires it.

7. Separate connection time from operation time

Current PowerShell uses -ConnectionTimeoutSeconds for establishing the connection and -OperationTimeoutSeconds for operations after connection. -TimeoutSec remains an alias for the connection timeout for compatibility. DNS resolution can itself take longer than a very small connection timeout, so a two-second number is not a universal guarantee for name-resolution failure.

try {
    Invoke-WebRequest -Uri 'https://example.com/' `
        -ConnectionTimeoutSeconds 5 `
        -OperationTimeoutSeconds 15 `
        -ErrorAction Stop | Out-Null
    'HTTP request succeeded.'
}
catch {
    [pscustomobject]@{
        Type    = $_.Exception.GetType().FullName
        Message = $_.Exception.Message
        WhenUtc = [datetime]::UtcNow
    }
}

8. Redirects are new requests, not magic movement

An HTTP redirect tells the client to request another URI. Invoke-WebRequest follows redirects by default up to a limit. -MaximumRedirection 0 disables following them. Authentication headers and method preservation across redirects require care because a redirect can cross origins.

# Inspect redirect behavior deliberately in environments where you expect it.
$params = @{
    Uri                = 'https://example.com/'
    MaximumRedirection = 5
    ConnectionTimeoutSeconds = 5
}
Invoke-WebRequest @params | Select-Object StatusCode,BaseResponse

9. Save a download safely and verify what arrived

Downloading is a state change on the local filesystem. Write into a disposable workspace, keep the response metadata with -PassThru, and validate the status/content before treating the file as trusted input.

$lab = Join-Path ([System.IO.Path]::GetTempPath()) 'ps-ch13-http'
New-Item -ItemType Directory -Path $lab -Force | Out-Null
$outFile = Join-Path $lab 'example.html'

$response = Invoke-WebRequest -Uri 'https://example.com/' `
    -OutFile $outFile -PassThru `
    -ConnectionTimeoutSeconds 5 -OperationTimeoutSeconds 15

$file = Get-Item -LiteralPath $outFile
[pscustomobject]@{
    StatusCode  = $response.StatusCode
    ContentType = ($response.Headers['Content-Type'] -join ', ')
    Bytes       = $file.Length
    SHA256      = (Get-FileHash -LiteralPath $outFile -Algorithm SHA256).Hash
}

Remove-Item -LiteralPath $lab -Recurse -Force

10. Keep response/data objects separate from human formatting

Do not pipe a response through Format-Table and then expect to serialize it as useful machine data. Inspect or project the response object first. Formatting belongs at the final human-display boundary, exactly as Chapter 3 established.

$response = Invoke-WebRequest 'https://example.com/'
$result = [pscustomobject]@{
    Uri         = $response.BaseResponse.RequestMessage.RequestUri.AbsoluteUri
    StatusCode  = $response.StatusCode
    ContentType = ($response.Headers['Content-Type'] -join ', ')
    Bytes       = $response.RawContentLength
}
$result
$result | ConvertTo-Json

11. Lab: inspect an HTTP endpoint as evidence

$uri = [uri]'https://example.com/'
$started = [datetime]::UtcNow
try {
    $response = Invoke-WebRequest -Uri $uri `
        -ConnectionTimeoutSeconds 5 -OperationTimeoutSeconds 15 `
        -ErrorAction Stop

    [pscustomobject]@{
        Uri          = $uri.AbsoluteUri
        Success      = $true
        StatusCode   = $response.StatusCode
        ContentType  = ($response.Headers['Content-Type'] -join ', ')
        Bytes        = $response.RawContentLength
        StartedUtc   = $started
        FinishedUtc  = [datetime]::UtcNow
    }
}
catch {
    [pscustomobject]@{
        Uri          = $uri.AbsoluteUri
        Success      = $false
        ErrorType    = $_.Exception.GetType().FullName
        ErrorMessage = $_.Exception.Message
        StartedUtc   = $started
        FinishedUtc  = [datetime]::UtcNow
    }
}

12. Verification checklist

  • You can identify the scheme, host, path, query, and fragment of a URI.
  • You can explain methods, status codes, headers, body, and Content-Type.
  • You can inspect an Invoke-WebRequest response object instead of scraping terminal text.
  • You use explicit connection/operation timeouts and catch network/TLS/HTTP failures.
  • You do not disable certificate validation as a production shortcut.
  • You can save a response into a disposable file and verify metadata/hash.

13. Common mistakes

  • Calling every HTTP problem a “network problem.”
  • Ignoring status codes because the response body contains text.
  • Disabling certificate validation instead of fixing trust.
  • Saving a download and immediately executing/parsing it without validation.
  • Using a tiny timeout and assuming it bounds DNS resolution perfectly.
  • Formatting response objects before downstream automation consumes them.

14. Knowledge check

Question 1. What does HTTPS add to HTTP?

Question 2. Why is HTTP 503 different from a TCP timeout?

Question 3. Which object is useful when you need status, headers, content, and HTML links?

Question 4. Should -SkipCertificateCheck be a production reliability strategy?

Question 5. Why use -PassThru with -OutFile when verifying a download?

15. Summary and next bridge

You can now reason about HTTP as a protocol rather than a magic web command. Invoke-WebRequest exposes the response boundary directly. Lesson 3 builds on that model with Invoke-RestMethod, where JSON responses become PowerShell objects and REST-style resource operations become easier to automate.

16. Authoritative references

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.