Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] Header-only packages cannot be uploaded to Conan server #13672

Closed
tygokf opened this issue Apr 11, 2023 · 12 comments
Closed

[bug] Header-only packages cannot be uploaded to Conan server #13672

tygokf opened this issue Apr 11, 2023 · 12 comments
Assignees

Comments

@tygokf
Copy link

tygokf commented Apr 11, 2023

Environment details

  • Operating System+version: Windows 11
  • Conan version: 2.0.2
  • Python version: 3.11.1

Steps to reproduce

  1. Download the following files:
  2. Remove the txt file extension, because GitHub doesn't allow all file extensions
  3. Edit the paths to the volumes that you want to mount in docker_compose.yaml on line 16/17
    Defaults are: C:\tmp\conan_server and C:\tmp\data
  4. Run the following commands in the directory with the downloaded files:
    • docker build . --tag my-conan-server
    • docker compose -f docker_compose.yaml up -d
    • conan remote add my-server http://127.0.0.1:9400
  5. Replace the generated server.conf in C:\tmp\conan_server with the provided server.conf in this bug report
  6. Run docker restart my-conan-server, such that the new server.conf will be used.
  7. Clone and go to the provided header-only example from docs.conan.io:
    • git clone https://github.com/conan-io/examples2.git
    • cd examples2/tutorial/creating_packages/other_packages/header_only
  8. Create and upload header only package to my_server (username: demo, password: demo):
    • conan create .
    • conan upload sum/0.1 -r my-server

Logs

conan upload sum/0.1 -r my-server
                                                                                                                                                                                                                                                                                                                                 
Checking which revisions exist in the remote server
Preparing artifacts to upload
Please log in to "my-server" to perform this action. Execute "conan user" command.
Please enter a password for "demo" account:
Uploading artifacts
Uploading recipe 'sum/0.1#8d9f1fb3655adcb348befcd8374c5292'
Uploading package 'sum/0.1#8d9f1fb3655adcb348befcd8374c5292:da39a3ee5e6b4b0d3255bfef95601890afd80709#622519f3e17bb6008141219c3f322ec0'
ERROR: 
Error uploading file: conaninfo.txt, '400: Bad Request'
ERROR: Execute upload again to retry upload the failed files: conaninfo.txt. [Remote: my-server]
@tygokf
Copy link
Author

tygokf commented Apr 11, 2023

We assume that this bug is caused by an empty conaninfo.txt, which is empty because a header only package doesn't contain any settings or options. When we add an empty options or settings section to the conaninfo.txt, then the error disappears.

@memsharded
Copy link
Member

Hi @tygokf

Thanks for your report.

We assume that this bug is caused by an empty conaninfo.txt, which is empty because a header only package doesn't contain any settings or options. When we add an empty options or settings section to the conaninfo.txt, then the error disappears.

This is a bit surprising. I have just tested launching locally a conan_server (no docker, just python server_launcher.py), and uploading a header-only package with an empty conaninfo.txt, and it works, I have seen the conaninfo.txt in the server and I can do a conan list *:* -r=server and it will display an empty info field. So I would say that having an empty conaninfo.txt shouldn't be the cause.

I'd tend to think that this could be related to the infra/docker setup. First thing I would try is dropping the shared/mount folders, and using a folder inside the docker image.

@tygokf
Copy link
Author

tygokf commented Apr 13, 2023

Thank you for your quick response @memsharded

After some further investigation we figured out that the use of gunicorn was causing issues. With your suggested way to start the server python server_launcher.py uploading header-only packages was no issue. We were starting the webserver with gunicorn -b 0000:9400 --log-level INFO -w 64 -t 300 conans.server.server_launcher:app, as was suggested by the conan 1.0 documention. This way appears to be incompatible with conan 2.0 header-only packages.

@memsharded
Copy link
Member

That is interesting, thanks for the feedback @tygokf, it is a bit surprising that gunicorn will cause this specific effect, as in theory using it should be quite transparent to the application layer, no idea what would be happening there to specifically fail at empty conaninfo.txt files.

If you are concerned about performance, maybe you want to consider using ArtifactoryCE?. It is completely free, and it can be way more performant than conan_server, both in transfer and in storage (and it also has better permissions, web UI, etc.)

@jakubgros
Copy link

Hi. I have a problem that is likely to be related. For some reason, the Conan client adds the "Transfer-Encoding:chunked" header when uploading conaninfo.txt, which is causing the Error while parsing chunked transfer body. error to be returned. Such a header is not added when uploading conanmanifest.txt, so there is no problem uploading such a file.
My colleague discovered, that when we don't use Gunicorn and start the server with the command below, the problem disappears:
/usr/bin/conan_server -d /root/.conan_server

It seems that Gunicorn, which is used as a web server in entrypoint of the docker images, can't handle chunked requests properly - bottlepy/bottle#845 (comment)

Below are instructions on how to reproduce the problem and debug it:

  1. Create server.conf:
[server]
jwt_secret: DCmRPIPvumdgpucgdugtWeOG
jwt_expire_minutes: 120

ssl_enabled: False
port: 9300
public_port:
host_name: localhost
authorize_timeout: 1800
disk_storage_path: ./data
disk_authorize_timeout: 1800
updown_secret: YKLSrXZPbxSRtHgsKybwEvcA

[write_permissions]
*/*@*/*: demo

[read_permissions]
*/*@*/*: *

[users]
default_user: defaultpass
demo: demo
  1. Start a docker container and mount the config:
    docker run -it --name="conan_server_debug" --rm -v "$PWD/server.conf:/root/.conan_server/server.conf" -p "9300:9300" conanio/conan_server:1.61.0
  2. In a separate console - docker exec -it conan_server_debug watch -n 1 rm -rf /root/.conan_server/data - this is necessary because on the first upload, all the files except conaninfo.txt are uploaded. On the second upload attempt, the server discovers other files in the package are already uploaded, so it does accept anything claiming that the package is already uploaded. Thus without it, the bug is not reproducible on subsequent runs.
  3. On host run: conan remote add local http://localhost:9301
  4. In a separate console on the host run: mitmproxy --mode reverse:http://localhost:9300/ -p 9301 --set keep_host_header=true - this will give you the possibility to inspect the requests being sent between Conan client and conan_server. If you decide not to use it, adjust ports, so as not to go through the proxy.
  5. Checkout the [email protected]:conan-io/conan-center-index.git repository(I'm on the fca6afcc1 commit), go to recipes/decimal_for_cpp and build with conan create all/conanfile.py --version="1.18"
  6. Try to upload the package conan upload -vvv "decimal_for_cpp/1.18" -r local.When asked for credentials provide user: demo, password: demo. In the Conan client you'll get Error uploading file: conaninfo.txt, '400: Bad Request' error and in mitmproxy you will see a PUT request returning code 400. When you check the returned response in mitmproxy, you will see the "Error while parsing chunked transfer body." error.

@jabbas
Copy link

jabbas commented Oct 12, 2023

I've tried the same but using uwsgi instead of gunicorn - results are same.

How to reproduce uwsgi way?
Build the docker image using:

FROM conanio/conan_server:latest
RUN apk add uwsgi uwsgi-python3 uwsgi-http
ENTRYPOINT uwsgi --plugin python3 --plugin http -w conans.server.server_launcher:app --http 0:9300 --workers 4

Then run with:

docker run -t -p 9300:9300 -v $HOME/server.conf:/root/.conan_server/server.conf

Then run points 5, 6, 7 from @jakubgros post

@jabbas
Copy link

jabbas commented Oct 12, 2023

Tested with hypercorn and uvicorn - results are the same.

Looks like something is wrong when we are doing PUT with conaninfo.txt file which is 0 bytes:

image

@memsharded
Copy link
Member

Hi all,

I have had another quick look to Conan codebase, still nothing that I think that could fix this.
It still sounds more like a bad luck coincidence of several infra parts (bottle, gunicorn, etc), all the other servers do not have issues with an empty conaninfo.txt file. I will ask @davidsanfal in case he might help checking the infra.

@eivindt
Copy link

eivindt commented Oct 31, 2023

I've created a draft pull request #15036 that is one way to work around this.

I'm not sure if you want to add this to conan, as it seems to be the web servers that are at fault, but it's a simple workaround in conan.

It fixes the problem by passing an empty string rather than a file handle to requests.put when uploading empty files.

@memsharded
Copy link
Member

This is not planned to be workarounded in Conan, it seems an issue in some specific webservers, not Conan, see summary in #15036 (comment). Thanks!

@jabbas
Copy link

jabbas commented Apr 29, 2024

Looks like @eivindt made a PR to python-requests that fixes that bug. Big kudos @eivindt!

When psf/requests#6568 will be merged (and looks like it should be soon). It should be fixed here too.

@memsharded
Copy link
Member

The PR is scheduled for requests 2.32, and the Conan requirements.txt already allows it with requests>=2.25, <3.0.0, so it will be good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants