minimal-http-client-post

This commit is contained in:
Andy Green 2018-04-03 13:19:12 +08:00
parent a017c4b0eb
commit 719f735309
5 changed files with 488 additions and 0 deletions

View file

@ -2,4 +2,5 @@
---|---
minimal-http-client-hugeurl|Sends a > 2.5KB URL to warmcat.com
minimal-http-client-multi|Connects to and reads https://warmcat.com, 8 times concurrently
minimal-http-client-post|POSTs a form containing an uploaded file and a form variable, and captures the response
minimal-http-client|Connects to and reads https://warmcat.com

View file

@ -0,0 +1,77 @@
cmake_minimum_required(VERSION 2.8)
include(CheckCSourceCompiles)
set(SAMP lws-minimal-http-client-post)
set(SRCS minimal-http-client-post.c)
# If we are being built as part of lws, confirm current build config supports
# reqconfig, else skip building ourselves.
#
# If we are being built externally, confirm installed lws was configured to
# support reqconfig, else error out with a helpful message about the problem.
#
MACRO(require_lws_config reqconfig _val result)
if (DEFINED ${reqconfig})
if (${reqconfig})
set (rq 1)
else()
set (rq 0)
endif()
else()
set(rq 0)
endif()
if (${_val} EQUAL ${rq})
set(SAME 1)
else()
set(SAME 0)
endif()
if (LWS_WITH_MINIMAL_EXAMPLES AND NOT ${SAME})
if (${_val})
message("${SAMP}: skipping as lws being built without ${reqconfig}")
else()
message("${SAMP}: skipping as lws built with ${reqconfig}")
endif()
set(${result} 0)
else()
if (LWS_WITH_MINIMAL_EXAMPLES)
set(MET ${SAME})
else()
CHECK_C_SOURCE_COMPILES("#include <libwebsockets.h>\nint main(void) {\n#if defined(${reqconfig})\n return 0;\n#else\n fail;\n#endif\n return 0;\n}\n" HAS_${reqconfig})
if (NOT DEFINED HAS_${reqconfig} OR NOT HAS_${reqconfig})
set(HAS_${reqconfig} 0)
else()
set(HAS_${reqconfig} 1)
endif()
if ((HAS_${reqconfig} AND ${_val}) OR (NOT HAS_${reqconfig} AND NOT ${_val}))
set(MET 1)
else()
set(MET 0)
endif()
endif()
if (NOT MET)
if (${_val})
message(FATAL_ERROR "This project requires lws must have been configured with ${reqconfig}")
else()
message(FATAL_ERROR "Lws configuration of ${reqconfig} is incompatible with this project")
endif()
endif()
endif()
ENDMACRO()
set(requirements 1)
require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)
if (requirements)
add_executable(${SAMP} ${SRCS})
if (websockets_shared)
target_link_libraries(${SAMP} websockets_shared)
add_dependencies(${SAMP} websockets_shared)
else()
target_link_libraries(${SAMP} websockets)
endif()
endif()

View file

@ -0,0 +1,74 @@
# lws minimal http client POST
This example demonstrates a multipart POST to
https://libwebsockets.org/testserver/formtest
setting both a form variable and uploading a
short file.
The result of the POST form processing is captured
and displayed in a hexdump.
This is programmatically POSTing to the same
form you can access at
https://libwebsockets.org/testserver
in the "POST" tab with file upload.
By default the client action occurs using http/2 if
your lws was built with `-DLWS_WITH_HTTP2=1`.
## build
```
$ cmake . && make
```
## usage
```
$ ./lws-minimal-http-client-post
[2018/04/03 13:13:10:7891] USER: LWS minimal http client - POST
[2018/04/03 13:13:10:7905] NOTICE: Creating Vhost 'default' (serving disabled), 1 protocols, IPv6 on
[2018/04/03 13:13:10:7984] NOTICE: created client ssl context for default
[2018/04/03 13:13:12:8444] USER: LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER
[2018/04/03 13:13:12:8444] USER: LWS_CALLBACK_CLIENT_HTTP_WRITEABLE
[2018/04/03 13:13:12:8445] USER: LWS_CALLBACK_CLIENT_HTTP_WRITEABLE
[2018/04/03 13:13:12:8445] USER: LWS_CALLBACK_CLIENT_HTTP_WRITEABLE
[2018/04/03 13:13:13:1437] USER: LWS_CALLBACK_CLIENT_HTTP_WRITEABLE
[2018/04/03 13:13:13:1440] USER: LWS_CALLBACK_CLIENT_HTTP_WRITEABLE
[2018/04/03 13:13:13:1440] USER: RECEIVE_CLIENT_HTTP_READ: read 402
[2018/04/03 13:13:13:1441] NOTICE:
[2018/04/03 13:13:13:1441] NOTICE: 0000: 3C 68 74 6D 6C 3E 3C 62 6F 64 79 3E 3C 68 31 3E <html><body><h1>
[2018/04/03 13:13:13:1441] NOTICE: 0010: 46 6F 72 6D 20 72 65 73 75 6C 74 73 20 28 61 66 Form results (af
[2018/04/03 13:13:13:1441] NOTICE: 0020: 74 65 72 20 75 72 6C 64 65 63 6F 64 69 6E 67 29 ter urldecoding)
[2018/04/03 13:13:13:1441] NOTICE: 0030: 3C 2F 68 31 3E 3C 74 61 62 6C 65 3E 3C 74 72 3E </h1><table><tr>
[2018/04/03 13:13:13:1441] NOTICE: 0040: 3C 74 64 3E 4E 61 6D 65 3C 2F 74 64 3E 3C 74 64 <td>Name</td><td
[2018/04/03 13:13:13:1441] NOTICE: 0050: 3E 4C 65 6E 67 74 68 3C 2F 74 64 3E 3C 74 64 3E >Length</td><td>
[2018/04/03 13:13:13:1441] NOTICE: 0060: 56 61 6C 75 65 3C 2F 74 64 3E 3C 2F 74 72 3E 3C Value</td></tr><
[2018/04/03 13:13:13:1441] NOTICE: 0070: 74 72 3E 3C 74 64 3E 3C 62 3E 74 65 78 74 3C 2F tr><td><b>text</
[2018/04/03 13:13:13:1441] NOTICE: 0080: 62 3E 3C 2F 74 64 3E 3C 74 64 3E 31 33 3C 2F 74 b></td><td>13</t
[2018/04/03 13:13:13:1441] NOTICE: 0090: 64 3E 3C 74 64 3E 6D 79 20 74 65 78 74 20 66 69 d><td>my text fi
[2018/04/03 13:13:13:1441] NOTICE: 00A0: 65 6C 64 3C 2F 74 64 3E 3C 2F 74 72 3E 3C 74 72 eld</td></tr><tr
[2018/04/03 13:13:13:1441] NOTICE: 00B0: 3E 3C 74 64 3E 3C 62 3E 73 65 6E 64 3C 2F 62 3E ><td><b>send</b>
[2018/04/03 13:13:13:1441] NOTICE: 00C0: 3C 2F 74 64 3E 3C 74 64 3E 30 3C 2F 74 64 3E 3C </td><td>0</td><
[2018/04/03 13:13:13:1442] NOTICE: 00D0: 74 64 3E 4E 55 4C 4C 3C 2F 74 64 3E 3C 2F 74 72 td>NULL</td></tr
[2018/04/03 13:13:13:1442] NOTICE: 00E0: 3E 3C 74 72 3E 3C 74 64 3E 3C 62 3E 66 69 6C 65 ><tr><td><b>file
[2018/04/03 13:13:13:1442] NOTICE: 00F0: 3C 2F 62 3E 3C 2F 74 64 3E 3C 74 64 3E 30 3C 2F </b></td><td>0</
[2018/04/03 13:13:13:1442] NOTICE: 0100: 74 64 3E 3C 74 64 3E 4E 55 4C 4C 3C 2F 74 64 3E td><td>NULL</td>
[2018/04/03 13:13:13:1442] NOTICE: 0110: 3C 2F 74 72 3E 3C 74 72 3E 3C 74 64 3E 3C 62 3E </tr><tr><td><b>
[2018/04/03 13:13:13:1442] NOTICE: 0120: 75 70 6C 6F 61 64 3C 2F 62 3E 3C 2F 74 64 3E 3C upload</b></td><
[2018/04/03 13:13:13:1442] NOTICE: 0130: 74 64 3E 30 3C 2F 74 64 3E 3C 74 64 3E 4E 55 4C td>0</td><td>NUL
[2018/04/03 13:13:13:1442] NOTICE: 0140: 4C 3C 2F 74 64 3E 3C 2F 74 72 3E 3C 2F 74 61 62 L</td></tr></tab
[2018/04/03 13:13:13:1442] NOTICE: 0150: 6C 65 3E 3C 62 72 3E 3C 62 3E 66 69 6C 65 6E 61 le><br><b>filena
[2018/04/03 13:13:13:1442] NOTICE: 0160: 6D 65 3A 3C 2F 62 3E 20 6D 79 66 69 6C 65 2E 74 me:</b> myfile.t
[2018/04/03 13:13:13:1442] NOTICE: 0170: 78 74 2C 20 3C 62 3E 6C 65 6E 67 74 68 3C 2F 62 xt, <b>length</b
[2018/04/03 13:13:13:1442] NOTICE: 0180: 3E 20 34 34 3C 2F 62 6F 64 79 3E 3C 2F 68 74 6D > 44</body></htm
[2018/04/03 13:13:13:1442] NOTICE: 0190: 6C 3E l>
[2018/04/03 13:13:13:1442] NOTICE:
[2018/04/03 13:13:13:1442] USER: LWS_CALLBACK_COMPLETED_CLIENT_HTTP
[2018/04/03 13:13:13:1455] USER: Completed
```

View file

@ -0,0 +1,92 @@
-----BEGIN CERTIFICATE-----
MIIGCDCCA/CgAwIBAgIQKy5u6tl1NmwUim7bo3yMBzANBgkqhkiG9w0BAQwFADCB
hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwMjEy
MDAwMDAwWhcNMjkwMjExMjM1OTU5WjCBkDELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
Q09NT0RPIENBIExpbWl0ZWQxNjA0BgNVBAMTLUNPTU9ETyBSU0EgRG9tYWluIFZh
bGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAI7CAhnhoFmk6zg1jSz9AdDTScBkxwtiBUUWOqigwAwCfx3M28Sh
bXcDow+G+eMGnD4LgYqbSRutA776S9uMIO3Vzl5ljj4Nr0zCsLdFXlIvNN5IJGS0
Qa4Al/e+Z96e0HqnU4A7fK31llVvl0cKfIWLIpeNs4TgllfQcBhglo/uLQeTnaG6
ytHNe+nEKpooIZFNb5JPJaXyejXdJtxGpdCsWTWM/06RQ1A/WZMebFEh7lgUq/51
UHg+TLAchhP6a5i84DuUHoVS3AOTJBhuyydRReZw3iVDpA3hSqXttn7IzW3uLh0n
c13cRTCAquOyQQuvvUSH2rnlG51/ruWFgqUCAwEAAaOCAWUwggFhMB8GA1UdIwQY
MBaAFLuvfgI9+qbxPISOre44mOzZMjLUMB0GA1UdDgQWBBSQr2o6lFoL2JDqElZz
30O0Oija5zAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV
HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgG
BmeBDAECATBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNv
bS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggrBgEFBQcB
AQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9E
T1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21v
ZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAE4rdk+SHGI2ibp3wScF9BzWRJ2p
mj6q1WZmAT7qSeaiNbz69t2Vjpk1mA42GHWx3d1Qcnyu3HeIzg/3kCDKo2cuH1Z/
e+FE6kKVxF0NAVBGFfKBiVlsit2M8RKhjTpCipj4SzR7JzsItG8kO3KdY3RYPBps
P0/HEZrIqPW1N+8QRcZs2eBelSaz662jue5/DJpmNXMyYE7l3YphLG5SEXdoltMY
dVEVABt0iN3hxzgEQyjpFv3ZBdRdRydg1vs4O2xyopT4Qhrf7W8GjEXCBgCq5Ojc
2bXhc3js9iPc0d1sjhqPpepUfJa3w/5Vjo1JXvxku88+vZbrac2/4EjxYoIQ5QxG
V/Iz2tDIY+3GH5QFlkoakdH368+PUq4NCNk+qKBR6cGHdNXJ93SrLlP7u3r7l+L4
HyaPs9Kg4DdbKDsx5Q5XLVq4rXmsXiBmGqW5prU5wfWYQ//u+aen/e7KJD2AFsQX
j4rBYKEMrltDR5FL1ZoXX/nUh8HCjLfn4g8wGTeGrODcQgPmlKidrv0PJFGUzpII
0fxQ8ANAe4hZ7Q7drNJ3gjTcBpUC2JD5Leo31Rpg0Gcg19hCC0Wvgmje3WYkN5Ap
lBlGGSW4gNfL1IYoakRwJiNiqZ+Gb7+6kHDSVneFeO/qJakXzlByjAA6quPbYzSf
+AZxAeKCINT+b72x
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFdDCCBFygAwIBAgIQJ2buVutJ846r13Ci/ITeIjANBgkqhkiG9w0BAQwFADBv
MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk
ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF
eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow
gYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYD
VQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkq
hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAkehUktIKVrGsDSTdxc9EZ3SZKzejfSNw
AHG8U9/E+ioSj0t/EFa9n3Byt2F/yUsPF6c947AEYe7/EZfH9IY+Cvo+XPmT5jR6
2RRr55yzhaCCenavcZDX7P0N+pxs+t+wgvQUfvm+xKYvT3+Zf7X8Z0NyvQwA1onr
ayzT7Y+YHBSrfuXjbvzYqOSSJNpDa2K4Vf3qwbxstovzDo2a5JtsaZn4eEgwRdWt
4Q08RWD8MpZRJ7xnw8outmvqRsfHIKCxH2XeSAi6pE6p8oNGN4Tr6MyBSENnTnIq
m1y9TBsoilwie7SrmNnu4FGDwwlGTm0+mfqVF9p8M1dBPI1R7Qu2XK8sYxrfV8g/
vOldxJuvRZnio1oktLqpVj3Pb6r/SVi+8Kj/9Lit6Tf7urj0Czr56ENCHonYhMsT
8dm74YlguIwoVqwUHZwK53Hrzw7dPamWoUi9PPevtQ0iTMARgexWO/bTouJbt7IE
IlKVgJNp6I5MZfGRAy1wdALqi2cVKWlSArvX31BqVUa/oKMoYX9w0MOiqiwhqkfO
KJwGRXa/ghgntNWutMtQ5mv0TIZxMOmm3xaG4Nj/QN370EKIf6MzOi5cHkERgWPO
GHFrK+ymircxXDpqR+DDeVnWIBqv8mqYqnK8V0rSS527EPywTEHl7R09XiidnMy/
s1Hap0flhFMCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73g
JMtUGjAdBgNVHQ4EFgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQD
AgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9
MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVy
bmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6
Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAGS/g/FfmoXQ
zbihKVcN6Fr30ek+8nYEbvFScLsePP9NDXRqzIGCJdPDoCpdTPW6i6FtxFQJdcfj
Jw5dhHk3QBN39bSsHNA7qxcS1u80GH4r6XnTq1dFDK8o+tDb5VCViLvfhVdpfZLY
Uspzgb8c8+a4bmYRBbMelC1/kZWSWfFMzqORcUx8Rww7Cxn2obFshj5cqsQugsv5
B5a6SE2Q8pTIqXOi6wZ7I53eovNNVZ96YUWYGGjHXkBrI/V5eu+MtWuLt29G9Hvx
PUsE2JOAWVrgQSQdso8VYFhH2+9uRv0V9dlfmrPb2LjkQLPNlzmuhbsdjrzch5vR
pu/xO28QOG8=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
-----END CERTIFICATE-----

View file

@ -0,0 +1,244 @@
/*
* lws-minimal-http-client-post
*
* Copyright (C) 2018 Andy Green <andy@warmcat.com>
*
* This file is made available under the Creative Commons CC0 1.0
* Universal Public Domain Dedication.
*
* This demonstrates the a minimal http client using lws and POST.
*
* It POSTs both form data and a file to the form at
* https://libwebsockets.org/testserver/formtest and dumps
* the html page received generated by the POST handler.
*/
#include <libwebsockets.h>
#include <string.h>
#include <signal.h>
static int interrupted;
static struct lws *client_wsi;
struct pss {
char boundary[32];
char body_part;
};
static int
callback_http(struct lws *wsi, enum lws_callback_reasons reason,
void *user, void *in, size_t len)
{
struct pss *pss = (struct pss *)user;
char buf[LWS_PRE + 1024], *start = &buf[LWS_PRE], *p = start,
*end = &buf[sizeof(buf) - 1];
uint8_t **up, *uend;
uint32_t r;
int n;
switch (reason) {
/* because we are protocols[0] ... */
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
lwsl_err("CLIENT_CONNECTION_ERROR: %s\n",
in ? (char *)in : "(null)");
client_wsi = NULL;
break;
/* ...callbacks related to receiving the result... */
case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
lwsl_user("LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: response %d\n",
lws_http_client_http_response(wsi));
break;
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
lwsl_user("RECEIVE_CLIENT_HTTP_READ: read %d\n", (int)len);
lwsl_hexdump_notice(in, len);
return 0; /* don't passthru */
case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
n = sizeof(buf) - LWS_PRE;
if (lws_http_client_read(wsi, &p, &n) < 0)
return -1;
return 0; /* don't passthru */
case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
lwsl_user("LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n");
client_wsi = NULL;
break;
/* ...callbacks related to generating the POST... */
case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
lwsl_user("LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER\n");
up = (uint8_t **)in;
uend = *up + len - 1;
/* generate a random boundary string */
lws_get_random(lws_get_context(wsi), &r, sizeof(r));
lws_snprintf(pss->boundary, sizeof(pss->boundary) - 1,
"---boundary-%08x", r);
n = lws_snprintf(buf, sizeof(buf) - 1,
"multipart/form-data; boundary=%s", pss->boundary);
if (lws_add_http_header_by_token(wsi,
WSI_TOKEN_HTTP_CONTENT_TYPE,
(uint8_t *)buf, n, up, uend))
return 1;
/*
* Notice because we are sending multipart/form-data we can
* usually rely on the server to understand where the form
* payload ends without having to give it an overall
* content-length (which can be troublesome to compute ahead
* of generating the data to send).
*
* Tell lws we are going to send the body next...
*/
lws_client_http_body_pending(wsi, 1);
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE:
lwsl_user("LWS_CALLBACK_CLIENT_HTTP_WRITEABLE\n");
n = LWS_WRITE_HTTP;
/*
* For a small body like this, we could prepare it in memory and
* send it all at once. But to show how to handle, eg,
* arbitrary-sized file payloads, or huge form-data fields, the
* sending is done in multiple passes through the event loop.
*/
switch (pss->body_part++) {
case 0:
/* notice every usage of the boundary starts with -- */
p += lws_snprintf(p, end - p, "--%s\xd\xa"
"content-disposition: "
"form-data; name=\"text\"\xd\xa"
"\xd\xa"
"my text field"
"\xd\xa", pss->boundary);
break;
case 1:
p += lws_snprintf(p, end - p,
"--%s\xd\xa"
"content-disposition: form-data; name=\"file\";"
"filename=\"myfile.txt\"\xd\xa"
"content-type: text/plain\xd\xa"
"\xd\xa"
"This is the contents of the "
"uploaded file.\xd\xa"
"\xd\xa", pss->boundary);
break;
case 2:
p += lws_snprintf(p, end - p, "--%s--\xd\xa",
pss->boundary);
lws_client_http_body_pending(wsi, 0);
/* necessary to support H2, it means we will write no
* more on this stream */
n = LWS_WRITE_HTTP_FINAL;
break;
default:
/*
* We can get extra callbacks here, if nothing to do,
* then do nothing.
*/
return 0;
}
if (lws_write(wsi, (uint8_t *)start, lws_ptr_diff(p, start), n)
!= lws_ptr_diff(p, start))
return 1;
if (n != LWS_WRITE_HTTP_FINAL)
lws_callback_on_writable(wsi);
return 0;
default:
break;
}
return lws_callback_http_dummy(wsi, reason, user, in, len);
}
static const struct lws_protocols protocols[] = {
{
"http",
callback_http,
sizeof(struct pss),
0,
},
{ NULL, NULL, 0, 0 }
};
static void
sigint_handler(int sig)
{
interrupted = 1;
}
int main(int argc, char **argv)
{
struct lws_context_creation_info info;
struct lws_client_connect_info i;
struct lws_context *context;
int n = 0;
signal(SIGINT, sigint_handler);
lws_set_log_level(LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE
/* for LLL_ verbosity above NOTICE to be built into lws,
* lws must have been configured and built with
* -DCMAKE_BUILD_TYPE=DEBUG instead of =RELEASE */
/* | LLL_INFO */ /* | LLL_PARSER */ /* | LLL_HEADER */
/* | LLL_EXT */ /* | LLL_CLIENT */ /* | LLL_LATENCY */
/* | LLL_DEBUG */, NULL);
lwsl_user("LWS minimal http client - POST\n");
memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
info.protocols = protocols;
#if defined(LWS_WITH_MBEDTLS)
/*
* OpenSSL uses the system trust store. mbedTLS has to be told which
* CA to trust explicitly.
*/
info.client_ssl_ca_filepath = "./libwebsockets.org.cer";
#endif
context = lws_create_context(&info);
if (!context) {
lwsl_err("lws init failed\n");
return 1;
}
memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */
i.context = context;
i.port = 443;
i.address = "libwebsockets.org";
i.path = "/testserver/formtest";
i.ssl_connection = /* LCCSCF_NOT_H2 | */ LCCSCF_USE_SSL;
i.host = i.address;
i.origin = i.address;
i.method = "POST";
i.protocol = protocols[0].name;
i.pwsi = &client_wsi;
lws_client_connect_via_info(&i);
while (n >= 0 && client_wsi && !interrupted)
n = lws_service(context, 1000);
lws_context_destroy(context);
lwsl_user("Completed\n");
return 0;
}