Repository: traefik/traefik (language: go)

Issue:
Traefik return preflight requests with 200 but log DownstreamStatus with 0 in access log
### Welcome!

- [X] Yes, I've searched similar issues on [GitHub](https://github.com/traefik/traefik/issues) and didn't find any.
- [X] Yes, I've searched similar issues on the [Traefik community forum](https://community.traefik.io) and didn't find any.

### What did you do?

Maybe this is a question, if I do
```
curl -v -X OPTIONS -H "Origin: whatever" -H "Access-Control-Request-Method: GET" https://mydomain.com
```

I got status code 200, but in access log I see:

```
DownstreamStatus: 0
OriginStatus: 0
```

Is this expected? Should `DownstreamStatus` log `200` instead?

### What did you see instead?

I see `DownstreamStatus: 0` in access log.

### What version of Traefik are you using?

v2.9.10

### What is your environment & configuration?

Added header middleware with cors headers.

### If applicable, please paste the log output in DEBUG level

_No response_


Discussion / hints:
Hello @yongzhang,

Thanks for the bug report.
Hello, 
We encounter the same as in logs as in metric:
<img width="1706" alt="image" src="https://github.com/traefik/traefik/assets/96792836/83922324-51f5-4ccf-aac2-a5cabf04becd">
Important note here, for http 200 is shown, but not for websocket. 
Hello @andrejshapal,

> Important note here, for http 200 is shown, but not for websocket.

As websocket connections are plain TCP connections, this behavior is expected

Fix patch:
diff --git a/integration/fixtures/access_log_config.toml b/integration/fixtures/access_log_config.toml
index 68e6537887..8d954450e2 100644
--- a/integration/fixtures/access_log_config.toml
+++ b/integration/fixtures/access_log_config.toml
@@ -20,6 +20,8 @@
     address = ":8007"
   [entryPoints.digestAuth]
     address = ":8008"
+  [entryPoints.preflight]
+    address = ":8009"
 
 [api]
   insecure = true
diff --git a/integration/resources/compose/access_log.yml b/integration/resources/compose/access_log.yml
index 91b1a0c489..3ae761c4a0 100644
--- a/integration/resources/compose/access_log.yml
+++ b/integration/resources/compose/access_log.yml
@@ -85,6 +85,16 @@ services:
       traefik.http.middlewares.wl.ipwhitelist.sourcerange: 8.8.8.8/32
       traefik.http.services.service3.loadbalancer.server.port: 80
 
+  preflightCORS:
+    image: traefik/whoami
+    labels:
+      traefik.enable: true
+      traefik.http.routers.rt-preflightCORS.entryPoints: preflight
+      traefik.http.routers.rt-preflightCORS.rule: Host(`preflight.docker.local`)
+      traefik.http.routers.rt-preflightCORS.middlewares: preflightCORS
+      traefik.http.middlewares.preflightCORS.headers.accessControlAllowMethods: OPTIONS, GET
+      traefik.http.services.preflightCORS.loadbalancer.server.port: 80
+
 networks:
   default:
     name: traefik-test-network
diff --git a/pkg/middlewares/headers/header.go b/pkg/middlewares/headers/header.go
index 8e48f9f33f..3930277c87 100644
--- a/pkg/middlewares/headers/header.go
+++ b/pkg/middlewares/headers/header.go
@@ -53,6 +53,7 @@ func NewHeader(next http.Handler, cfg dynamic.Headers) (*Header, error) {
 func (s *Header) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 	// Handle Cors headers and preflight if configured.
 	if isPreflight := s.processCorsHeaders(rw, req); isPreflight {
+		rw.WriteHeader(http.StatusOK)
 		return
 	}
 


Test patch:
diff --git a/integration/access_log_test.go b/integration/access_log_test.go
index d279f993f7..1f25a94710 100644
--- a/integration/access_log_test.go
+++ b/integration/access_log_test.go
@@ -592,6 +592,53 @@ func (s *AccessLogSuite) TestAccessLogAuthFrontendSuccess(c *check.C) {
 	checkNoOtherTraefikProblems(c)
 }
 
+func (s *AccessLogSuite) TestAccessLogPreflightHeadersMiddleware(c *check.C) {
+	ensureWorkingDirectoryIsClean()
+
+	expected := []accessLogValue{
+		{
+			formatOnly: false,
+			code:       "200",
+			user:       "-",
+			routerName: "rt-preflightCORS",
+			serviceURL: "-",
+		},
+	}
+
+	// Start Traefik
+	cmd, display := s.traefikCmd(withConfigFile("fixtures/access_log_config.toml"))
+	defer display(c)
+
+	err := cmd.Start()
+	c.Assert(err, checker.IsNil)
+	defer s.killCmd(cmd)
+
+	checkStatsForLogFile(c)
+
+	waitForTraefik(c, "preflightCORS")
+
+	// Verify Traefik started OK
+	checkTraefikStarted(c)
+
+	// Test preflight response
+	req, err := http.NewRequest(http.MethodOptions, "http://127.0.0.1:8009/", nil)
+	c.Assert(err, checker.IsNil)
+	req.Host = "preflight.docker.local"
+	req.Header.Set("Origin", "whatever")
+	req.Header.Set("Access-Control-Request-Method", "GET")
+
+	err = try.Request(req, 500*time.Millisecond, try.StatusCodeIs(http.StatusOK))
+	c.Assert(err, checker.IsNil)
+
+	// Verify access.log output as expected
+	count := checkAccessLogExactValuesOutput(c, expected)
+
+	c.Assert(count, checker.GreaterOrEqualThan, len(expected))
+
+	// Verify no other Traefik problems
+	checkNoOtherTraefikProblems(c)
+}
+
 func checkNoOtherTraefikProblems(c *check.C) {
 	traefikLog, err := os.ReadFile(traefikTestLogFile)
 	c.Assert(err, checker.IsNil)