---
name: ws_upgrader
kind: function
lang: go
domain: infra
version: "1.0.0"
purity: impure
signature: "func WSUpgrader(w http.ResponseWriter, r *http.Request, origins []string) (*websocket.Conn, error)"
description: "Hace el upgrade de una conexion HTTP a WebSocket usando nhooyr.io/websocket. Si origins contiene `*` se acepta cualquier origen (InsecureSkipVerify=true), en caso contrario OriginPatterns valida el header Origin del cliente con filepath.Match. Retorna el *websocket.Conn listo para Read/Write o un error si el handshake falla."
tags: [websocket, upgrade, http, server, infra, realtime]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, net/http, "nhooyr.io/websocket"]
params:
  - name: w
    desc: "http.ResponseWriter del request entrante. Debe soportar hijack (no envuelto en middlewares que rompan Hijacker)."
  - name: r
    desc: "*http.Request del cliente que pide el upgrade. Debe contener los headers Connection: Upgrade y Upgrade: websocket."
  - name: origins
    desc: "lista de patrones de origen permitidos (filepath.Match). Si contiene `*` se aceptan todos los origenes (modo inseguro, solo dev). Para produccion: lista explicita de hosts (ej: [`example.com`, `app.example.com`])."
output: "*websocket.Conn listo para Read/Write y error. Si el handshake falla (origen no autorizado, headers invalidos), el writer ya tiene la respuesta de error escrita."
tested: true
tests: ["upgradea conexion valida con origen permitido", "rechaza origen no permitido", "acepta cualquier origen con `*`"]
test_file_path: "functions/infra/ws_test.go"
file_path: "functions/infra/ws_upgrader.go"
---

## Ejemplo

```go
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
    conn, err := WSUpgrader(w, r, []string{"example.com", "app.example.com"})
    if err != nil {
        return // error ya escrito al writer
    }
    defer conn.Close(websocket.StatusNormalClosure, "")

    for {
        _, data, err := conn.Read(r.Context())
        if err != nil {
            return
        }
        conn.Write(r.Context(), websocket.MessageText, data) // echo
    }
})
```

## Notas

`nhooyr.io/websocket` exige un patron de origen explicito o `InsecureSkipVerify=true` — no admite `*` como pattern. Esta funcion traduce `["*"]` a InsecureSkipVerify para mantener una API uniforme con CORS.

Para produccion: nunca usar `["*"]`, listar hosts explicitos. La validacion protege contra cross-origin WebSocket hijacking (un sitio malicioso abriendo WS al servidor desde el browser de la victima).
