PUT Request to Update Issue Labels Clears All Labels Instead of Replacing With The New One #13853

Closed
opened 2025-11-02 10:55:06 -06:00 by GiteaMirror · 2 comments
Owner

Originally created by @bhavishya-8 on GitHub (Dec 19, 2024).

Description

I am trying to update the labels of an issue in Gitea using the following PUT request:

curl -X PUT  --location 'https://demo.gitea.com/api/v1/repos/bhavishya-8/sample/issues/1/labels' -d '{"labels": ["status/working-on-this"]}'   --header 'Authorization: Bearer TOKEN' -v

Instead of replacing the labels with the new label as expected, this request clears the label section of the issue, leaving it empty.

Expected Behavior:
The labels of the issue should be updated to include only the ones specified in the request.

Actual Behavior:
The label section becomes empty after the request is executed.

Gitea Version

1.22.4

Can you reproduce the bug on the Gitea demo site?

Yes

Log Gist

(base) bhavishya@bhavishya:~/Desktop$ curl -X PUT --location 'https://demo.gitea.com/api/v1/repos/bhavishya-8/sample/issues/1/labels' -d '{"labels": ["status/working-on-this"]}' --header 'Authorization: Bearer TOKEN' -v * Host demo.gitea.com:443 was resolved. * IPv6: 2600:1f14:b94:3b00:f434:fb42:37d1:4d43 * IPv4: 52.40.189.212 * Trying 52.40.189.212:443... * Trying [2600:1f14:b94:3b00:f434:fb42:37d1:4d43]:443... * Connected to demo.gitea.com (52.40.189.212) port 443 * ALPN: curl offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * CAfile: /home/bhavishya/anaconda3/ssl/cacert.pem * CApath: none * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519 / id-ecPublicKey * ALPN: server accepted h2 * Server certificate: * subject: CN=demo.gitea.com * start date: Nov 21 02:35:09 2024 GMT * expire date: Feb 19 02:35:08 2025 GMT * subjectAltName: host "demo.gitea.com" matched cert's "demo.gitea.com" * issuer: C=US; O=Let's Encrypt; CN=E6 * SSL certificate verify ok. * Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384 * Certificate level 1: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using sha256WithRSAEncryption * Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * using HTTP/2 * [HTTP/2] [1] OPENED stream for https://demo.gitea.com/api/v1/repos/bhavishya-8/sample/issues/1/labels * [HTTP/2] [1] [:method: PUT] * [HTTP/2] [1] [:scheme: https] * [HTTP/2] [1] [:authority: demo.gitea.com] * [HTTP/2] [1] [:path: /api/v1/repos/bhavishya-8/sample/issues/1/labels] * [HTTP/2] [1] [user-agent: curl/8.5.0] * [HTTP/2] [1] [accept: /] * [HTTP/2] [1] [authorization: Bearer TOKEN] * [HTTP/2] [1] [content-length: 38] * [HTTP/2] [1] [content-type: application/x-www-form-urlencoded] > PUT /api/v1/repos/bhavishya-8/sample/issues/1/labels HTTP/2 > Host: demo.gitea.com > User-Agent: curl/8.5.0 > Accept: / > Authorization: Bearer TOKEN > Content-Length: 38 > Content-Type: application/x-www-form-urlencoded > < HTTP/2 200 < alt-svc: h3=":443"; ma=2592000 < cache-control: max-age=0, private, must-revalidate, no-transform < content-type: application/json;charset=utf-8 < date: Thu, 19 Dec 2024 06:39:37 GMT < server: Caddy < x-content-type-options: nosniff < x-frame-options: SAMEORIGIN < content-length: 3 < [] * Connection #0 to host demo.gitea.com left intact

Screenshots

Initially, I added the status/new label to a sample issue on demo.gitea.com:
image

Then, I ran the following command:

curl -X PUT  --location 'https://demo.gitea.com/api/v1/repos/bhavishya-8/sample/issues/1/labels' -d '{"labels": ["status/working-on-this"]}'   --header 'Authorization: Bearer TOKEN' -v

After reloading the page, I found that the label was removed, and it was not replaced by the status/working-on-this label:
image

Both labels exist in the labels section:
image

Git Version

2.34.1

Operating System

Ubuntu 22.04.4 LTS

How are you running Gitea?

I am running this on demo.gitea.com

Database

None

Originally created by @bhavishya-8 on GitHub (Dec 19, 2024). ### Description I am trying to update the labels of an issue in Gitea using the following PUT request: ``` curl -X PUT --location 'https://demo.gitea.com/api/v1/repos/bhavishya-8/sample/issues/1/labels' -d '{"labels": ["status/working-on-this"]}' --header 'Authorization: Bearer TOKEN' -v ``` Instead of replacing the labels with the new label as expected, this request clears the label section of the issue, leaving it empty. Expected Behavior: The labels of the issue should be updated to include only the ones specified in the request. Actual Behavior: The label section becomes empty after the request is executed. ### Gitea Version 1.22.4 ### Can you reproduce the bug on the Gitea demo site? Yes ### Log Gist (base) bhavishya@bhavishya:~/Desktop$ curl -X PUT --location 'https://demo.gitea.com/api/v1/repos/bhavishya-8/sample/issues/1/labels' -d '{"labels": ["status/working-on-this"]}' --header 'Authorization: Bearer TOKEN' -v * Host demo.gitea.com:443 was resolved. * IPv6: 2600:1f14:b94:3b00:f434:fb42:37d1:4d43 * IPv4: 52.40.189.212 * Trying 52.40.189.212:443... * Trying [2600:1f14:b94:3b00:f434:fb42:37d1:4d43]:443... * Connected to demo.gitea.com (52.40.189.212) port 443 * ALPN: curl offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * CAfile: /home/bhavishya/anaconda3/ssl/cacert.pem * CApath: none * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519 / id-ecPublicKey * ALPN: server accepted h2 * Server certificate: * subject: CN=demo.gitea.com * start date: Nov 21 02:35:09 2024 GMT * expire date: Feb 19 02:35:08 2025 GMT * subjectAltName: host "demo.gitea.com" matched cert's "demo.gitea.com" * issuer: C=US; O=Let's Encrypt; CN=E6 * SSL certificate verify ok. * Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384 * Certificate level 1: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using sha256WithRSAEncryption * Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * using HTTP/2 * [HTTP/2] [1] OPENED stream for https://demo.gitea.com/api/v1/repos/bhavishya-8/sample/issues/1/labels * [HTTP/2] [1] [:method: PUT] * [HTTP/2] [1] [:scheme: https] * [HTTP/2] [1] [:authority: demo.gitea.com] * [HTTP/2] [1] [:path: /api/v1/repos/bhavishya-8/sample/issues/1/labels] * [HTTP/2] [1] [user-agent: curl/8.5.0] * [HTTP/2] [1] [accept: */*] * [HTTP/2] [1] [authorization: Bearer TOKEN] * [HTTP/2] [1] [content-length: 38] * [HTTP/2] [1] [content-type: application/x-www-form-urlencoded] > PUT /api/v1/repos/bhavishya-8/sample/issues/1/labels HTTP/2 > Host: demo.gitea.com > User-Agent: curl/8.5.0 > Accept: */* > Authorization: Bearer TOKEN > Content-Length: 38 > Content-Type: application/x-www-form-urlencoded > < HTTP/2 200 < alt-svc: h3=":443"; ma=2592000 < cache-control: max-age=0, private, must-revalidate, no-transform < content-type: application/json;charset=utf-8 < date: Thu, 19 Dec 2024 06:39:37 GMT < server: Caddy < x-content-type-options: nosniff < x-frame-options: SAMEORIGIN < content-length: 3 < [] * Connection #0 to host demo.gitea.com left intact ### Screenshots Initially, I added the status/new label to a sample issue on demo.gitea.com: ![image](https://github.com/user-attachments/assets/e4a9031e-48c8-477b-963a-c45eef23fd01) Then, I ran the following command: ``` curl -X PUT --location 'https://demo.gitea.com/api/v1/repos/bhavishya-8/sample/issues/1/labels' -d '{"labels": ["status/working-on-this"]}' --header 'Authorization: Bearer TOKEN' -v ``` After reloading the page, I found that the label was removed, and it was not replaced by the status/working-on-this label: ![image](https://github.com/user-attachments/assets/f33917a5-5bf5-4581-95e5-1a2cbb9ba9d2) Both labels exist in the labels section: ![image](https://github.com/user-attachments/assets/80c95180-c1da-4173-8408-3b8275dedcfe) ### Git Version 2.34.1 ### Operating System Ubuntu 22.04.4 LTS ### How are you running Gitea? I am running this on demo.gitea.com ### Database None
GiteaMirror added the topic/api label 2025-11-02 10:55:06 -06:00
Author
Owner

@kemzeb commented on GitHub (Dec 20, 2024):

From looking at your curl input, you appear to be passing the -d option arg. From reading the man page, this will set the Content-Type header to application/x-www-form-urlencoded:

You must modify this header so that the Gitea API will interpret your request body properly, e.g.:

➜  gitea git:(main) ✗ curl -X 'PUT' --location \
  'http://localhost:3000/api/v1/repos/korvax/test/issues/1/labels' \
  -H 'authorization: Basic xxxxxxxxxxxxxxxxxxxxx \
  -H 'Content-Type: application/json' \
  -d '{
  "labels": [
    "status/working-on-this"
  ]
}' -v
* Host localhost:3000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:3000...
* connect to ::1 port 3000 from ::1 port 52608 failed: Connection refused
*   Trying 127.0.0.1:3000...
* Connected to localhost (127.0.0.1) port 3000
> PUT /api/v1/repos/korvax/test/issues/1/labels HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/8.5.0
> Accept: */*
> authorization: Basic xxxxxxxxxxxxxxxxxxxxx
> Content-Type: application/json
> Content-Length: 50
> 
< HTTP/1.1 200 OK
< Cache-Control: max-age=0, private, must-revalidate, no-transform
< Content-Type: application/json;charset=utf-8
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< Date: Fri, 20 Dec 2024 03:43:31 GMT
< Content-Length: 180
< 
[{"id":52,"name":"status/working-on-this","exclusive":true,"is_archived":false,"color":"fef2c0","description":"","url":"http://localhost:3000/api/v1/repos/korvax/test/labels/52"}]

I'm not sure why we don't enforce the request's MIME type anyways.

@kemzeb commented on GitHub (Dec 20, 2024): From looking at your curl input, you appear to be passing the `-d` option arg. From reading the man page, this will set the `Content-Type` header to `application/x-www-form-urlencoded`: You must modify this header so that the Gitea API will interpret your request body properly, e.g.: ``` ➜ gitea git:(main) ✗ curl -X 'PUT' --location \ 'http://localhost:3000/api/v1/repos/korvax/test/issues/1/labels' \ -H 'authorization: Basic xxxxxxxxxxxxxxxxxxxxx \ -H 'Content-Type: application/json' \ -d '{ "labels": [ "status/working-on-this" ] }' -v * Host localhost:3000 was resolved. * IPv6: ::1 * IPv4: 127.0.0.1 * Trying [::1]:3000... * connect to ::1 port 3000 from ::1 port 52608 failed: Connection refused * Trying 127.0.0.1:3000... * Connected to localhost (127.0.0.1) port 3000 > PUT /api/v1/repos/korvax/test/issues/1/labels HTTP/1.1 > Host: localhost:3000 > User-Agent: curl/8.5.0 > Accept: */* > authorization: Basic xxxxxxxxxxxxxxxxxxxxx > Content-Type: application/json > Content-Length: 50 > < HTTP/1.1 200 OK < Cache-Control: max-age=0, private, must-revalidate, no-transform < Content-Type: application/json;charset=utf-8 < X-Content-Type-Options: nosniff < X-Frame-Options: SAMEORIGIN < Date: Fri, 20 Dec 2024 03:43:31 GMT < Content-Length: 180 < [{"id":52,"name":"status/working-on-this","exclusive":true,"is_archived":false,"color":"fef2c0","description":"","url":"http://localhost:3000/api/v1/repos/korvax/test/labels/52"}] ``` I'm not sure why we don't enforce the request's MIME type anyways.
Author
Owner

@bhavishya-8 commented on GitHub (Dec 22, 2024):

Thank you for the detailed explanation and the example! after setting the Content-Type header to application/json worked perfectly.

@bhavishya-8 commented on GitHub (Dec 22, 2024): Thank you for the detailed explanation and the example! after setting the Content-Type header to application/json worked perfectly.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/gitea#13853