asciinema / asciinema

Terminal session recorder 📹

Home Page:https://asciinema.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Manual upload of recording fails on Ubuntu 20.04

sskras opened this issue · comments

It works if I upload the small recording (195 bytes), but fails when I try to upload the 100 kB:
image

The curl session return HTTP/2 500 code and says "Internal Server Error":

$ curl -v -u sskras:$(cat ~/.config/asciinema/install-id) https://asciinema.org/api/asciicasts -F asciicast=@/tmp/tmpqsscy294-ascii.cast; echo
*   Trying 109.107.37.0:443...
* TCP_NODELAY set
* Connected to asciinema.org (109.107.37.0) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* 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
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.asciinema.org
*  start date: May  8 10:34:01 2022 GMT
*  expire date: Aug  6 10:34:00 2022 GMT
*  subjectAltName: host "asciinema.org" matched cert's "asciinema.org"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Server auth using Basic with user 'sskras'
* Using Stream ID: 1 (easy handle 0x55d77a0d9090)
> POST /api/asciicasts HTTP/2
> Host: asciinema.org
> authorization: Basic c3NrcmFzOjE4MTI2MjVmLTE4ODktNDE2Ni04ZWY2LTcxNDlkODFhMzEzOQ==
> user-agent: curl/7.68.0
> accept: */*
> content-length: 102619
> content-type: multipart/form-data; boundary=------------------------2e0590fa72362da5
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
* We are completely uploaded and fine
< HTTP/2 500
< cache-control: max-age=0, private, must-revalidate
< content-type: text/plain; charset=utf-8
< date: Thu, 23 Jun 2022 09:37:24 GMT
< server: nginx
< x-request-id: Fvs2WRTm0Cq1it4EbE2i
< content-length: 21
<
* Connection #0 to host asciinema.org left intact
Internal Server Error

Any ideas on how to proceed?

I must admit that the bigger recording comes from the Asciinema crash due to the filled disk space.
The file was truncated, maybe its structure (the JSON?) is damaged. Just a thought.

OK, looks like it's supposed to be a multiline file containing JSONs separated by newlines:
https://blog.asciinema.org/#asciicast-v2-file-format

So I checked last line of the file:

$ tail -1 /tmp/tmpqsscy294-ascii.cast; echo "<EOF>"
[351.038637, "o", "without-pdo-firebird --without-pdo-mysql --without-pdo-oci --without-pdo-odbc --without-pdo-pgsql --wit<EOF>

So it really looks like it's truncated:

Now fixing end of the file and counting total lines:

$ { cat /tmp/tmpqsscy294-ascii.cast; echo; } | wc -l
886

... and doing a per-line check using jsonlint (from python3-demjson package):

$ time { cat /tmp/tmpqsscy294-ascii.cast; echo; } | while read LINE; do I=$((I+1)); echo $LINE | jsonlint -q || { echo -n "Line $I: "; echo $LINE | jsonlint; echo; } ; done
Line 886: <stdin>:1:122: Error: Line terminator characters must be escaped inside string literals: 'U+000A'
   |  At line 1, column 122, offset 122
   |  String started at line 1, column 18, offset 18
<stdin>:2:0: Error: String literal is not terminated
   |  At line 2, column 0, offset 123 (AT-END)
   |    near text: True
   |  String started at line 1, column 18, offset 18
<stdin>:2:0: Error: String literal is not terminated with a quotation mark
   |  At line 2, column 0, offset 123 (AT-END)
   |    near text: True
   |  String started at line 1, column 18, offset 18
<stdin>:2:0: Error: Array literal (list) is not terminated
   |  At line 2, column 0, offset 123 (AT-END)
   |    near text: True
   |  Array started at line 1, column 0, offset 0 (AT-START)
<stdin>: has errors


real    0m23.535s
user    0m19.403s
sys     0m4.968s

So the problem seems to be in the last line only.

Making a copy:

$ cp -v /tmp/tmpqsscy294-ascii.cast .
'/tmp/tmpqsscy294-ascii.cast' -> './tmpqsscy294-ascii.cast'

Trying to fix:

$ echo " ...\"]" >> tmpqsscy294-ascii.cast
$ wc -l tmpqsscy294-ascii.cast
886 tmpqsscy294-ascii.cast

And voila, the error is gone:

$ time cat tmpqsscy294-ascii.cast | while read LINE; do I=$((I+1)); echo $LINE | jsonlint -q || { echo -n "Line $I: "; echo $LINE | jsonlint; echo; } ; done

real    0m23.513s
user    0m19.298s
sys     0m4.998s

Now trying to upload the adjusted copy:

$ curl -v -u sskras:$(cat ~/.config/asciinema/install-id) https://asciinema.org/api/asciicasts -F asciicast=@./tmpqsscy294-ascii.cast; echo
*   Trying 109.107.38.233:443...
* TCP_NODELAY set
* Connected to asciinema.org (109.107.38.233) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* 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
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.asciinema.org
*  start date: May  8 10:34:01 2022 GMT
*  expire date: Aug  6 10:34:00 2022 GMT
*  subjectAltName: host "asciinema.org" matched cert's "asciinema.org"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Server auth using Basic with user 'sskras'
* Using Stream ID: 1 (easy handle 0x557ba1f28090)
> POST /api/asciicasts HTTP/2
> Host: asciinema.org
> authorization: Basic c3NrcmFzOjE4MTI2MjVmLTE4ODktNDE2Ni04ZWY2LTcxNDlkODFhMzEzOQ==
> user-agent: curl/7.68.0
> accept: */*
> content-length: 102626
> content-type: multipart/form-data; boundary=------------------------6bc2e10c87f73d44
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
* We are completely uploaded and fine
< HTTP/2 201
< cache-control: max-age=0, private, must-revalidate
< content-type: text/plain; charset=utf-8
< date: Sat, 25 Jun 2022 09:55:12 GMT
< location: https://asciinema.org/a/5xzGJ3ddeftWXjc6Q8gZATwsk
< server: nginx
< strict-transport-security: max-age=15768000
< x-request-id: FvvUes30XezF4Q8EpfZy
< content-length: 78
<
View the recording at:

    https://asciinema.org/a/5xzGJ3ddeftWXjc6Q8gZATwsk
* Connection #0 to host asciinema.org left intact

Voila – it's here, on the server!

It would be nice if asciinema client had a functionality to fix the broken casts. Or at least to check their integrity.
Can this bugreport be left open with the latter request?

Glad you figured it out 👍

I don't think it's worth the extra work given user's full disk is not really asciinema's problem :)

@sickill, I partially disagree. Asciinema should:

(1) not crash when disk is full but exit gracefully;
(2) when crashing, it should handle the signal & tell that the output file is incomplete (in the stdout).

Should I file new issues about these points?

Then (3) web-service should output the human readable form of the error it encountered.
Not sure where is its repository / issue tracker.

In recently merged #545 I made it not crash, and instead show desktop notification "Write error, recording suspended". This should adress (1) and (2). It's doesn't immediately exit because you may be running some program whose interruption is undesired, so instead you get desktop notification and you can either continue your work / do cleanup, or just exit recorded program/shell immediately at your will.

Here's repo for the server component where we handle uploads: https://github.com/asciinema/asciinema-server/

Thanks for the details!