Class: Tep::Response

Inherits:
Object
  • Object
show all
Defined in:
lib/tep/response.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeResponse

Returns a new instance of Response.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/tep/response.rb', line 8

def initialize
  @status      = 200
  @headers     = Tep.str_hash
  @body        = ""
  @halted      = false
  @file_path   = ""
  # `Set-Cookie` is a header that can repeat; can't shove multiple
  # values into a Hash slot. Each entry here is one fully-formatted
  # Set-Cookie line, emitted verbatim by the writer.
  @set_cookies = [""]
  @set_cookies.delete_at(0)
  @streamer    = Streamer.new   # default no-op; only used when @streaming
  @streaming   = false
  # WebSocket upgrade slots. The Tep::Server::Scheduled write
  # path sees @upgrading_ws and, instead of writing the normal
  # status-line response body, emits the 101 handshake response
  # then drives the recv loop via Tep::WebSocket::Connection
  # until the connection closes.
  @upgrading_ws    = false
  @ws_accept_key   = ""
  @ws_driver       = Tep::WebSocket::Driver.new(0)
  # Last-Modified validator as epoch seconds (0 = unset). The header
  # carries the formatted date; this is kept for the conditional-GET
  # comparison against If-Modified-Since (issue #152).
  @lastmod_epoch   = 0
end

Instance Attribute Details

#bodyObject

Returns the value of attribute body.



6
7
8
# File 'lib/tep/response.rb', line 6

def body
  @body
end

#file_pathObject

Returns the value of attribute file_path.



6
7
8
# File 'lib/tep/response.rb', line 6

def file_path
  @file_path
end

#haltedObject

Returns the value of attribute halted.



6
7
8
# File 'lib/tep/response.rb', line 6

def halted
  @halted
end

#headersObject

Returns the value of attribute headers.



6
7
8
# File 'lib/tep/response.rb', line 6

def headers
  @headers
end

#lastmod_epochObject (readonly)

Returns the value of attribute lastmod_epoch.



37
38
39
# File 'lib/tep/response.rb', line 37

def lastmod_epoch
  @lastmod_epoch
end

#set_cookiesObject

Returns the value of attribute set_cookies.



6
7
8
# File 'lib/tep/response.rb', line 6

def set_cookies
  @set_cookies
end

#statusObject

Returns the value of attribute status.



6
7
8
# File 'lib/tep/response.rb', line 6

def status
  @status
end

#streamerObject

Returns the value of attribute streamer.



35
36
37
# File 'lib/tep/response.rb', line 35

def streamer
  @streamer
end

#streamingObject

Returns the value of attribute streaming.



35
36
37
# File 'lib/tep/response.rb', line 35

def streaming
  @streaming
end

#upgrading_wsObject

Returns the value of attribute upgrading_ws.



36
37
38
# File 'lib/tep/response.rb', line 36

def upgrading_ws
  @upgrading_ws
end

#ws_accept_keyObject

Returns the value of attribute ws_accept_key.



36
37
38
# File 'lib/tep/response.rb', line 36

def ws_accept_key
  @ws_accept_key
end

#ws_driverObject

Returns the value of attribute ws_driver.



36
37
38
# File 'lib/tep/response.rb', line 36

def ws_driver
  @ws_driver
end

Instance Method Details

#cache_control(v) ⇒ Object

Set the Cache-Control header verbatim.



42
43
44
45
# File 'lib/tep/response.rb', line 42

def cache_control(v)
  @headers["Cache-Control"] = v
  self
end

#etag(value) ⇒ Object

Strong ETag validator (quoted per RFC 7232).



60
61
62
63
# File 'lib/tep/response.rb', line 60

def etag(value)
  @headers["ETag"] = "\"" + value + "\""
  self
end

#expires(secs) ⇒ Object

Cacheable for ‘secs` seconds: set both Expires (absolute HTTP-date) and Cache-Control: max-age (relative).



53
54
55
56
57
# File 'lib/tep/response.rb', line 53

def expires(secs)
  @headers["Expires"]       = Sock.sphttp_http_date(Time.now.to_i + secs)
  @headers["Cache-Control"] = "max-age=" + secs.to_s
  self
end

#halted_close?Boolean

Returns:

  • (Boolean)


130
131
132
# File 'lib/tep/response.rb', line 130

def halted_close?
  @halted && @status >= 300
end

#last_modified(epoch) ⇒ Object

Last-Modified validator from Unix epoch seconds. Remembers the epoch so conditional GET can compare it to If-Modified-Since.



67
68
69
70
71
# File 'lib/tep/response.rb', line 67

def last_modified(epoch)
  @lastmod_epoch            = epoch
  @headers["Last-Modified"] = Sock.sphttp_http_date(epoch)
  self
end

#no_cacheObject



49
# File 'lib/tep/response.rb', line 49

def no_cache; cache_control("no-cache"); end

#no_storeObject

Common Cache-Control shortcuts.



48
# File 'lib/tep/response.rb', line 48

def no_store; cache_control("no-store"); end

#send_file(path) ⇒ Object



104
105
106
107
# File 'lib/tep/response.rb', line 104

def send_file(path)
  @file_path = path
  @body = ""
end

#set_body(s) ⇒ Object

Unconditional body setter. Same poly-write rationale as set_body_if_empty (self is unambiguously Response here, so the ‘@body = s` codegens correctly), but always assigns – used by Tep::Proxy, which writes the upstream body whether or not it’s empty (a 204 / empty upstream body must overwrite, not skip).



124
125
126
# File 'lib/tep/response.rb', line 124

def set_body(s)
  @body = s
end

#set_body_if_empty(s) ⇒ Object

Spinel’s polymorphic-receiver write codegen emits a no-op for ‘res.body = x` when called from a context that has a poly value, so we force the assignment through this method (where `self` is unambiguously Response).



113
114
115
116
117
# File 'lib/tep/response.rb', line 113

def set_body_if_empty(s)
  if @body.length == 0 && s.length > 0
    @body = s
  end
end

Sinatra-style cookie writer. ‘opts` is a Bag-of-strings (path, expires, max-age, domain, samesite, httponly, secure). Empty `opts` is fine: just writes “name=value”.



90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/tep/response.rb', line 90

def set_cookie(name, value, opts)
  line = name + "=" + Url.escape(value)
  if opts.length > 0
    opts.each do |k, v|
      if v.length == 0
        line = line + "; " + k          # bare flag (HttpOnly, Secure)
      else
        line = line + "; " + k + "=" + v
      end
    end
  end
  @set_cookies.push(line)
end

#set_status(n) ⇒ Object



128
# File 'lib/tep/response.rb', line 128

def set_status(n); @status = n; end

#start_stream(streamer) ⇒ Object



73
74
75
76
# File 'lib/tep/response.rb', line 73

def start_stream(streamer)
  @streamer  = streamer
  @streaming = true
end

#start_websocket(accept_key, driver) ⇒ Object

Mark the response as a WebSocket upgrade. The server writes a 101 Switching Protocols response with the accept-key, assigns the live client fd onto the driver, then runs the recv loop.



81
82
83
84
85
# File 'lib/tep/response.rb', line 81

def start_websocket(accept_key, driver)
  @upgrading_ws  = true
  @ws_accept_key = accept_key
  @ws_driver     = driver
end