pitchfork 0.18.0 → 0.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -340,18 +340,19 @@ static void write_value(VALUE self, struct http_parser *hp,
340
340
  }
341
341
  action host { rb_hash_aset(hp->env, g_http_host, STR_NEW(mark, fpc)); }
342
342
  action request_uri {
343
+ VALUE str;
344
+
343
345
  VALIDATE_MAX_URI_LENGTH(LEN(mark, fpc), REQUEST_URI);
344
- rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, fpc));
345
- }
346
- action fragment {
347
- VALIDATE_MAX_URI_LENGTH(LEN(mark, fpc), FRAGMENT);
348
- VALUE str = rb_hash_aset(hp->env, g_fragment, STR_NEW(mark, fpc));
346
+ str = rb_hash_aset(hp->env, g_request_uri, STR_NEW(mark, fpc));
347
+
349
348
  if (STR_CSTR_EQ(str, "*")) {
350
- VALUE str = rb_str_new("*", 1);
351
349
  rb_hash_aset(hp->env, g_path_info, str);
352
- rb_hash_aset(hp->env, g_request_path, str);
353
350
  }
354
351
  }
352
+ action fragment {
353
+ VALIDATE_MAX_URI_LENGTH(LEN(mark, fpc), FRAGMENT);
354
+ rb_hash_aset(hp->env, g_fragment, STR_NEW(mark, fpc));
355
+ }
355
356
  action start_query {MARK(start.query, fpc); }
356
357
  action query_string {
357
358
  VALIDATE_MAX_URI_LENGTH(LEN(start.query, fpc), QUERY_STRING);
@@ -364,9 +365,7 @@ static void write_value(VALUE self, struct http_parser *hp,
364
365
  VALIDATE_MAX_URI_LENGTH(LEN(mark, fpc), REQUEST_PATH);
365
366
  val = rb_hash_aset(hp->env, g_request_path, STR_NEW(mark, fpc));
366
367
 
367
- /* rack says PATH_INFO must start with "/" or be empty */
368
- if (!STR_CSTR_EQ(val, "*"))
369
- rb_hash_aset(hp->env, g_path_info, val);
368
+ rb_hash_aset(hp->env, g_path_info, val);
370
369
  }
371
370
  action add_to_chunk_size {
372
371
  hp->len.chunk = step_incr(hp->len.chunk, fc, 16);
@@ -92,6 +92,10 @@ module Pitchfork
92
92
  e['pitchfork.socket'] = socket
93
93
  e['rack.hijack'] = self
94
94
 
95
+ if PATH_INFO_REQUIRES_LEADING_SLASH && e['PATH_INFO'] == '*'
96
+ e.delete('PATH_INFO')
97
+ end
98
+
95
99
  e.merge!(DEFAULTS)
96
100
  end
97
101
 
@@ -803,7 +803,7 @@ module Pitchfork
803
803
  # assuming we haven't closed the socket, but don't get hung up
804
804
  # if the socket is already closed or broken. We'll always ensure
805
805
  # the socket is closed at the end of this function
806
- def handle_error(client, e)
806
+ def handle_error(client, e, response_written)
807
807
  code = case e
808
808
  when EOFError,Errno::ECONNRESET,Errno::EPIPE,Errno::ENOTCONN
809
809
  # client disconnected on us and there's nothing we can do
@@ -817,7 +817,7 @@ module Pitchfork
817
817
  Pitchfork.log_error(@logger, "app error", e)
818
818
  500
819
819
  end
820
- if code
820
+ if code && !response_written
821
821
  client.write_nonblock(err_response(code, @request.response_start_sent), exception: false)
822
822
  end
823
823
  client.close
@@ -842,6 +842,7 @@ module Pitchfork
842
842
  # once a client is accepted, it is processed in its entirety here
843
843
  # in 3 easy steps: read request, call app, write app response
844
844
  def process_client(client, worker, timeout_handler)
845
+ response_written = false
845
846
  env = nil
846
847
  @request = Pitchfork::HttpParser.new
847
848
  env = @request.read(client)
@@ -876,6 +877,7 @@ module Pitchfork
876
877
  end
877
878
  @request.headers? or headers = nil
878
879
  http_response_write(client, status, headers, body, @request)
880
+ response_written = true
879
881
  ensure
880
882
  body.respond_to?(:close) and body.close
881
883
  end
@@ -889,7 +891,7 @@ module Pitchfork
889
891
  end
890
892
  env
891
893
  rescue => application_error
892
- handle_error(client, application_error)
894
+ handle_error(client, application_error, response_written)
893
895
  env
894
896
  ensure
895
897
  if env
@@ -1012,9 +1014,10 @@ module Pitchfork
1012
1014
  when Message
1013
1015
  worker.update(client)
1014
1016
  else
1015
- request_env = process_client(client, worker, prepare_timeout(worker))
1016
- worker.increment_requests_count
1017
- @after_request_complete&.call(self, worker, request_env)
1017
+ if (request_env = process_client(client, worker, prepare_timeout(worker)))
1018
+ worker.increment_requests_count
1019
+ @after_request_complete&.call(self, worker, request_env)
1020
+ end
1018
1021
  end
1019
1022
 
1020
1023
  worker.update_deadline(@timeout)
@@ -69,7 +69,10 @@ module Pitchfork
69
69
  if io.is_a?(TCPSocket)
70
70
  # If we inherited a TCP Socket, calling #close directly could send FIN or RST.
71
71
  # So we first reopen /dev/null to avoid that.
72
- io.reopen(File::NULL)
72
+ begin
73
+ io.reopen(File::NULL)
74
+ rescue Errno::EBADF
75
+ end
73
76
  end
74
77
  begin
75
78
  io.close
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pitchfork
4
- VERSION = "0.18.0"
4
+ VERSION = "0.18.2"
5
5
  module Const
6
6
  UNICORN_VERSION = '6.1.0'
7
7
  end
data/lib/pitchfork.rb CHANGED
@@ -3,12 +3,7 @@
3
3
  require 'etc'
4
4
  require 'stringio'
5
5
  require 'io/wait'
6
-
7
- begin
8
- require 'rack'
9
- rescue LoadError
10
- warn 'rack not available, functionality reduced'
11
- end
6
+ require 'rack'
12
7
 
13
8
  # :stopdoc:
14
9
  # Pitchfork module containing all of the classes (include C extensions) for
@@ -21,6 +16,7 @@ end
21
16
  # applications, so applications should be written against the Rack SPEC
22
17
  # and not pitchfork internals.
23
18
  module Pitchfork
19
+ PATH_INFO_REQUIRES_LEADING_SLASH = Gem::Version.new(Rack.release) < Gem::Version.new('3.2.0')
24
20
 
25
21
  # Raised inside TeeInput when a client closes the socket inside the
26
22
  # application dispatch. This is always raised with an empty backtrace
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pitchfork
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0
4
+ version: 0.18.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean Boussier
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2025-07-17 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rack
@@ -53,6 +52,7 @@ files:
53
52
  - ".git-blame-ignore-revs"
54
53
  - ".gitattributes"
55
54
  - ".github/workflows/ci.yml"
55
+ - ".github/workflows/release.yml"
56
56
  - ".gitignore"
57
57
  - ".ruby-version"
58
58
  - CHANGELOG.md
@@ -126,7 +126,6 @@ licenses:
126
126
  - GPL-2.0+
127
127
  - Ruby
128
128
  metadata: {}
129
- post_install_message:
130
129
  rdoc_options: []
131
130
  require_paths:
132
131
  - lib
@@ -141,8 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
140
  - !ruby/object:Gem::Version
142
141
  version: '0'
143
142
  requirements: []
144
- rubygems_version: 3.5.9
145
- signing_key:
143
+ rubygems_version: 3.6.9
146
144
  specification_version: 4
147
145
  summary: Rack HTTP server for fast clients and Unix
148
146
  test_files: []