rwconn

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 30, 2022 License: Apache-2.0 Imports: 6 Imported by: 2

README

rwconn

Create a golang net.Conn using a Reader and a Writer.

The connection created implements Deadlines, that are used to stop a Read on a net.Conn without closing the connection.

This is really useful when you want to use the connection to send http traffic, since the net/http library uses the deadline the cancel reads without closing the connections, per example, for http.Hijacking

// c.mu must be held.
func (c *conn) hijackLocked() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
	if c.hijackedv {
		return nil, nil, ErrHijacked
	}
	c.r.abortPendingRead()

	c.hijackedv = true
	rwc = c.rwc
	rwc.SetDeadline(time.Time{})

	buf = bufio.NewReadWriter(c.bufr, bufio.NewWriter(rwc))
	if c.r.hasByte {
		if _, err := c.bufr.Peek(c.bufr.Buffered() + 1); err != nil {
			return nil, nil, fmt.Errorf("unexpected Peek failure reading buffered byte: %v", err)
		}
	}
	c.setState(rwc, StateHijacked, runHooks)
	return
}

Example

This module was created specifically to create connections over HTTP, those can achieved using the Request and Response bodies.

Server
// flushWriter
type flushWrite struct {
	w io.Writer
	f http.Flusher
}

func (w *flushWrite) Write(data []byte) (int, error) {
	n, err := w.w.Write(data)
	w.f.Flush()
	return n, err
}

func (w *flushWrite) Close() error {
	return nil
}


// handler to create a connection
func connHandler(w http.ResponseWriter, r *http.Request) {
			flusher, ok := w.(http.Flusher)
			if !ok {
				panic("flusher not support")
			}

			w.WriteHeader(http.StatusOK)
			flusher.Flush()
			fw := &flushWrite{w: w, f: flusher}
			doneCh := make(chan struct{})
			c2 = NewConn(r.Body, fw, SetWriteDelay(50*time.Millisecond), SetCloseHook(func() {
				// exit the handler
				close(doneCh)
			}))
			// signal connection is ready
			close(readyCh)
			// wait until the connection is closed to stop the handler
			<-doneCh
}
Client
pr, pw := io.Pipe()
client := &http.Client{}

// Create a request object to send to the server
req, err := http.NewRequest(http.MethodGet, srv.URL, pr)
if err != nil {
	return nil, nil, nil, err
}

// Perform the request
resp, err := client.Do(req)
if err != nil {
	return nil, nil, nil, err
}
if resp.StatusCode != 200 {
	return nil, nil, nil, fmt.Errorf("wrong status code")
}
c := NewConn(resp.Body, pw)
// manage connection
// ...

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewConn

func NewConn(r io.Reader, w io.Writer, options ...func(*RWConn)) net.Conn

func SetCloseHook

func SetCloseHook(f func()) func(*RWConn)

func SetWriteDelay

func SetWriteDelay(t time.Duration) func(*RWConn)

Types

type RWConn

type RWConn struct {
	// contains filtered or unexported fields
}

func (*RWConn) Close

func (c *RWConn) Close() error

Close closes the connection

func (*RWConn) Done

func (c *RWConn) Done() <-chan struct{}

func (*RWConn) LocalAddr

func (c *RWConn) LocalAddr() net.Addr

func (*RWConn) Read

func (c *RWConn) Read(data []byte) (int, error)

Read reads data from the connection

func (*RWConn) RemoteAddr

func (c *RWConn) RemoteAddr() net.Addr

func (*RWConn) SetDeadline

func (c *RWConn) SetDeadline(t time.Time) error

func (*RWConn) SetReadDeadline

func (c *RWConn) SetReadDeadline(t time.Time) error

func (*RWConn) SetWriteDeadline

func (c *RWConn) SetWriteDeadline(t time.Time) error

func (*RWConn) Write

func (c *RWConn) Write(data []byte) (int, error)

Write data to the connection in fixed chunks of 1024

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL