libcurl example

libcurl example

https://curl.se/libcurl/c/example.html도 참고하세요.

libcurl용 기본 API는 C로 되어 있으므로 이 장은 C로 작성된 예제에 초점을 맞춥니다. 그러나 libcurl용 언어 바인딩이 얇기 때문에 일반적으로 거의 동일한 기능을 노출하므로 여전히 흥미롭고 교육적일 수 있습니다. 다른 언어도 마찬가지입니다.

간단한 HTTP 페이지 가져오기

이 예제는 주어진 URL에서 HTML을 가져와서 stdout으로 보냅니다. 아마도 가장 간단한 libcurl 프로그램을 작성할 수 있습니다.

URL을 교체하면 물론 지원되는 다른 프로토콜을 통해서도 콘텐츠를 가져올 수 있습니다.

출력을 stdout으로 보내는 것은 기본 동작이며 일반적으로 실제로 원하는 것이 아닙니다. 대부분의 애플리케이션은 도착하는 데이터를 수신하기 위해 쓰기 콜백을 대신 설치합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <curl/curl.h>

int main(void)
{
CURL *curl;
CURLcode res;

curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/");

/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));

/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}

메모리에 페이지 가져오기

이 예는 수신된 데이터를 stdout(종종 원하는 것이 아님)으로 보내는 대신 수신 데이터가 증가함에 따라 확장되는 메모리 버퍼에 수신 데이터를 저장하는 전자의 변형입니다.

쓰기 콜백을 사용하여 데이터를 수신하여 이를 수행합니다.

이 예에서는 설정된 URL 체계와 함께 고정 URL 문자열을 사용하지만 물론 지원되는 다른 프로토콜을 사용하도록 이를 변경한 다음 대신 해당 프로토콜에서 리소스를 가져올 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <curl/curl.h>

struct MemoryStruct {
char *memory;
size_t size;
};

static size_t
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;

mem->memory = realloc(mem->memory, mem->size + realsize + 1);
if(mem->memory == NULL) {
/* out of memory */
printf("not enough memory (realloc returned NULL)\n");
return 0;
}

memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;

return realsize;
}

int main(void)
{
CURL *curl_handle;
CURLcode res;

struct MemoryStruct chunk;

chunk.memory = malloc(1); /* will be grown as needed by the realloc above */
chunk.size = 0; /* no data at this point */

curl_global_init(CURL_GLOBAL_ALL);

/* init the curl session */
curl_handle = curl_easy_init();

/* specify URL to get */
curl_easy_setopt(curl_handle, CURLOPT_URL, "https://www.example.com/");

/* send all data to this function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);

/* we pass our 'chunk' struct to the callback function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);

/* some servers do not like requests that are made without a user-agent
field, so we provide one */
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");

/* get it! */
res = curl_easy_perform(curl_handle);

/* check for errors */
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
else {
/*
* Now, our chunk.memory points to a memory block that is chunk.size
* bytes big and contains the remote file.
*
* Do something nice with it!
*/

printf("%lu bytes retrieved\n", (long)chunk.size);
}

/* cleanup curl stuff */
curl_easy_cleanup(curl_handle);

free(chunk.memory);

/* we are done with libcurl, so clean it up */
curl_global_cleanup();

return 0;
}

HTTP를 통해 로그인 양식 제출

HTTP를 통한 로그인 제출은 일반적으로 POST에서 제출할 데이터와 전송할 대상 URL을 정확히 파악하는 문제입니다.

로그인한 후 적절한 쿠키를 사용하면 대상 URL을 가져올 수 있습니다. 많은 로그인 시스템이 HTTP 리디렉션과 함께 작동하므로 libcurl이 이러한 리디렉션이 도착하면 이를 따르도록 요청합니다.

일부 로그인 양식은 이를 더 복잡하게 만들고 로그인 양식 등을 보여주는 페이지에서 쿠키를 얻어야 하므로 필요한 경우 이 코드를 약간 확장할 수 있습니다.

존재하지 않는 쿠키 파일을 전달함으로써 이 예제는 쿠키 파서를 활성화하여 로그인 응답의 응답이 도착할 때 들어오는 쿠키가 저장되고 리소스에 대한 후속 요청이 쿠키를 사용하고 우리가 실제로 올바르게 로그인했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>

int main(void)
{
CURL *curl;
CURLcode res;

static const char *postthis = "user=daniel&password=monkey123";

curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/login.cgi");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); /* redirects! */
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); /* no file */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
else {
/*
* After the login POST, we have received the new cookies. Switch
* over to a GET and ask for the login-protected URL.
*/
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/file");
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); /* no more POST */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "second curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}

FTP 디렉토리 목록 가져오기

이 예제는 주어진 URL에서 FTP 디렉토리 출력을 가져와서 stdout으로 보냅니다. URL의 후행 슬래시는 libcurl이 이를 디렉토리로 처리하도록 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <curl/curl.h>

int main(void)
{
CURL *curl;
CURLcode res;

curl_global_init(CURL_GLOBAL_DEFAULT);

curl = curl_easy_init();
if(curl) {
/*
* Make the URL end with a trailing slash!
*/
curl_easy_setopt(curl, CURLOPT_URL, "ftp://ftp.example.com/");

res = curl_easy_perform(curl);

/* always cleanup */
curl_easy_cleanup(curl);

if(CURLE_OK != res) {
/* we failed */
fprintf(stderr, "curl told us %d\n", res);
}
}

curl_global_cleanup();

return 0;
}

Non-blocking HTTP form-post

이 예제는 다중 인터페이스를 사용하여 다중 파트 form-post를 만듭니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <stdio.h>
#include <string.h>
#include <sys/time.h>

#include <curl/curl.h>

int main(void)
{
CURL *curl;

CURLM *multi_handle;
int still_running = 0;

curl_mime *form = NULL;
curl_mimepart *field = NULL;
struct curl_slist *headerlist = NULL;
static const char buf[] = "Expect:";

curl = curl_easy_init();
multi_handle = curl_multi_init();

if(curl && multi_handle) {
/* Create the form */
form = curl_mime_init(curl);

/* Fill in the file upload field */
field = curl_mime_addpart(form);
curl_mime_name(field, "sendfile");
curl_mime_filedata(field, "multi-post.c");

/* Fill in the filename field */
field = curl_mime_addpart(form);
curl_mime_name(field, "filename");
curl_mime_data(field, "multi-post.c", CURL_ZERO_TERMINATED);

/* Fill in the submit field too, even if this is rarely needed */
field = curl_mime_addpart(form);
curl_mime_name(field, "submit");
curl_mime_data(field, "send", CURL_ZERO_TERMINATED);

/* initialize custom header list (stating that Expect: 100-continue is not
wanted */
headerlist = curl_slist_append(headerlist, buf);

/* what URL that receives this POST */
curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/upload.cgi");
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);

curl_multi_add_handle(multi_handle, curl);

do {
CURLMcode mc = curl_multi_perform(multi_handle, &still_running);

if(still_running)
/* wait for activity, timeout or "nothing" */
mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL);

if(mc)
break;
} while(still_running);

curl_multi_cleanup(multi_handle);

/* always cleanup */
curl_easy_cleanup(curl);

/* then cleanup the form */
curl_mime_free(form);

/* free slist */
curl_slist_free_all(headerlist);
}
return 0;
}
공유하기