| 296 | } |
| 297 | |
| 298 | func dial(ctx context.Context, url string, opts *DialOptions) (*Conn, *http.Response, error) { |
| 299 | if opts == nil { |
| 300 | opts = &DialOptions{} |
| 301 | } |
| 302 | |
| 303 | url = strings.Replace(url, "http://", "ws://", 1) |
| 304 | url = strings.Replace(url, "https://", "wss://", 1) |
| 305 | |
| 306 | ws, err := wsjs.New(url, opts.Subprotocols) |
| 307 | if err != nil { |
| 308 | return nil, nil, err |
| 309 | } |
| 310 | |
| 311 | c := &Conn{ |
| 312 | ws: ws, |
| 313 | } |
| 314 | c.init() |
| 315 | |
| 316 | opench := make(chan struct{}) |
| 317 | releaseOpen := ws.OnOpen(func(e js.Value) { |
| 318 | close(opench) |
| 319 | }) |
| 320 | defer releaseOpen() |
| 321 | |
| 322 | select { |
| 323 | case <-ctx.Done(): |
| 324 | c.Close(StatusPolicyViolation, "dial timed out") |
| 325 | return nil, nil, ctx.Err() |
| 326 | case <-opench: |
| 327 | return c, &http.Response{ |
| 328 | StatusCode: http.StatusSwitchingProtocols, |
| 329 | }, nil |
| 330 | case <-c.closed: |
| 331 | return nil, nil, net.ErrClosed |
| 332 | } |
| 333 | } |
| 334 | |
| 335 | // Reader attempts to read a message from the connection. |
| 336 | // The maximum time spent waiting is bounded by the context. |