Skip to main content

Overview

The xrequestedwith middleware validates the X-Requested-With header, commonly used to identify AJAX requests and prevent CSRF attacks. Use it when you need:
  • AJAX request validation
  • CSRF protection layer
  • Request origin verification

Installation

import "github.com/go-mizu/mizu/middlewares/xrequestedwith"

Quick Start

app := mizu.New()

// Require X-Requested-With: XMLHttpRequest
app.Use(xrequestedwith.New())

Configuration

Options

OptionTypeDefaultDescription
RequiredbooltrueRequire header
Valuestring"XMLHttpRequest"Expected value
Methods[]stringState-changingMethods to check

Examples

Basic Validation

app.Use(xrequestedwith.New())
// Requires: X-Requested-With: XMLHttpRequest

Custom Value

app.Use(xrequestedwith.New(xrequestedwith.Options{
    Value: "MyApp",
}))
// Requires: X-Requested-With: MyApp

Specific Methods

app.Use(xrequestedwith.New(xrequestedwith.Options{
    Methods: []string{"POST", "PUT", "DELETE"},
}))

Detection Only

app.Use(xrequestedwith.New(xrequestedwith.Options{
    Required: false, // Don't reject, just detect
}))

app.Get("/", func(c *mizu.Ctx) error {
    if xrequestedwith.IsAJAX(c) {
        return c.JSON(200, data)
    }
    return c.HTML(200, page)
})

API Reference

Functions

// New creates X-Requested-With middleware
func New(opts ...Options) mizu.Middleware

// IsAJAX returns true if AJAX request
func IsAJAX(c *mizu.Ctx) bool

Client Usage

// jQuery sets this automatically
$.ajax({url: '/api', type: 'POST', data: data});

// Fetch/XMLHttpRequest
fetch('/api', {
    method: 'POST',
    headers: {
        'X-Requested-With': 'XMLHttpRequest'
    }
});

Technical Details

Implementation Overview

The middleware performs header validation through the following process:
  1. Method Filtering: Checks if the request method is in the skip list (default: GET, HEAD, OPTIONS)
  2. Path Filtering: Checks if the request path is in the skip paths list
  3. Header Validation: Compares the X-Requested-With header value (case-insensitive) against the expected value
  4. Error Handling: Returns either a custom error handler response or a default 400 Bad Request

Internal Components

  • Skip Methods Map: Pre-built map of HTTP methods to skip (defaults to safe methods)
  • Skip Paths Map: Pre-built map of paths to exclude from validation
  • Case-Insensitive Comparison: Uses strings.EqualFold for header value matching
  • Default Value: “XMLHttpRequest” is used when no custom value is specified

Function Variants

FunctionPurposeSkip Methods
New()Standard validationGET, HEAD, OPTIONS
WithOptions()Custom configurationConfigurable
Require(value)Custom value validationGET, HEAD, OPTIONS
AJAXOnly()Strict AJAX validationNone (checks all methods)
IsAJAX()Detection helperN/A (utility function)

Security Note

While X-Requested-With adds a layer of protection, it should not be the sole CSRF defense. Combine with:
  • CSRF tokens
  • SameSite cookies
  • Origin validation

Best Practices

  • Use as additional security layer
  • Combine with CSRF middleware
  • Don’t rely on it alone
  • Document header requirement for clients

Testing

The middleware includes comprehensive test coverage for various scenarios:
Test CaseDescriptionExpected Behavior
TestNew - with headerPOST request with X-Requested-With: XMLHttpRequestReturns 200 OK
TestNew - without headerPOST request without X-Requested-With headerReturns 400 Bad Request
TestNew_SkipsGETGET request without header (default skip)Returns 200 OK (skipped validation)
TestWithOptions_CustomValue - correct valueRequest with custom header value “CustomValue”Returns 200 OK
TestWithOptions_CustomValue - wrong valueRequest with XMLHttpRequest when CustomValue expectedReturns 400 Bad Request
TestWithOptions_SkipPaths - skipped pathPOST to /webhook (in skip list) without headerReturns 200 OK (path skipped)
TestWithOptions_SkipPaths - non-skipped pathPOST to /api (not in skip list) without headerReturns 400 Bad Request
TestWithOptions_ErrorHandlerRequest without header with custom error handlerReturns 403 Forbidden with custom JSON
TestRequireRequest with custom required value “FetchRequest”Returns 200 OK
TestAJAXOnly - with AJAX headerGET request with XMLHttpRequest headerReturns 200 OK
TestAJAXOnly - without AJAX headerGET request without header (no methods skipped)Returns 400 Bad Request
TestIsAJAX - is AJAXRequest with X-Requested-With: XMLHttpRequestIsAJAX() returns true
TestIsAJAX - not AJAXRequest without X-Requested-With headerIsAJAX() returns false
TestCaseInsensitivePOST with lowercase “xmlhttprequest”Returns 200 OK (case-insensitive match)
  • csrf - CSRF protection
  • cors - CORS handling
  • bot - Bot detection