network/http_post/source/main.c
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>
#include <3ds.h>
Result http_post(const char* url, const char* data)
{
Result ret=0;
httpcContext context;
char *newurl=NULL;
u32 statuscode=0;
u32 contentsize=0, readsize=0, size=0;
u8 *buf, *lastbuf;
printf("POSTing %s\n", url);
do {
ret = httpcOpenContext(&context, HTTPC_METHOD_POST, url, 0);
printf("return from httpcOpenContext: %" PRIx32 "\n",ret);
// This disables SSL cert verification, so https:// will be usable
ret = httpcSetSSLOpt(&context, SSLCOPT_DisableVerify);
printf("return from httpcSetSSLOpt: %" PRIx32 "\n",ret);
// Enable Keep-Alive connections
ret = httpcSetKeepAlive(&context, HTTPC_KEEPALIVE_ENABLED);
printf("return from httpcSetKeepAlive: %" PRIx32 "\n",ret);
// Set a User-Agent header so websites can identify your application
ret = httpcAddRequestHeaderField(&context, "User-Agent", "httpc-example/1.0.0");
printf("return from httpcAddRequestHeaderField: %" PRIx32 "\n",ret);
// Set a Content-Type header so websites can identify the format of our raw body data.
// If you want to send form data in your request, use:
//ret = httpcAddRequestHeaderField(&context, "Content-Type", "multipart/form-data");
// If you want to send raw JSON data in your request, use:
ret = httpcAddRequestHeaderField(&context, "Content-Type", "application/json");
printf("return from httpcAddRequestHeaderField: %" PRIx32 "\n",ret);
// Post specified data.
// If you want to add a form field to your request, use:
//ret = httpcAddPostDataAscii(&context, "data", value);
// If you want to add a form field containing binary data to your request, use:
//ret = httpcAddPostDataBinary(&context, "field name", yourBinaryData, length);
// If you want to add raw data to your request, use:
ret = httpcAddPostDataRaw(&context, (u32*)data, strlen(data));
printf("return from httpcAddPostDataRaw: %" PRIx32 "\n",ret);
ret = httpcBeginRequest(&context);
if(ret!=0){
httpcCloseContext(&context);
if(newurl!=NULL) free(newurl);
return ret;
}
ret = httpcGetResponseStatusCode(&context, &statuscode);
if(ret!=0){
httpcCloseContext(&context);
if(newurl!=NULL) free(newurl);
return ret;
}
if ((statuscode >= 301 && statuscode <= 303) || (statuscode >= 307 && statuscode <= 308)) {
if(newurl==NULL) newurl = malloc(0x1000); // One 4K page for new URL
if (newurl==NULL){
httpcCloseContext(&context);
return -1;
}
ret = httpcGetResponseHeader(&context, "Location", newurl, 0x1000);
url = newurl; // Change pointer to the url that we just learned
printf("redirecting to url: %s\n",url);
httpcCloseContext(&context); // Close this context before we try the next
}
} while ((statuscode >= 301 && statuscode <= 303) || (statuscode >= 307 && statuscode <= 308));
if(statuscode!=200){
printf("URL returned status: %" PRIx32 "\n", statuscode);
httpcCloseContext(&context);
if(newurl!=NULL) free(newurl);
return -2;
}
// This relies on an optional Content-Length header and may be 0
ret=httpcGetDownloadSizeState(&context, NULL, &contentsize);
if(ret!=0){
httpcCloseContext(&context);
if(newurl!=NULL) free(newurl);
return ret;
}
printf("reported size: %" PRIx32 "\n",contentsize);
// Start with a single page buffer
buf = (u8*)malloc(0x1000);
if(buf==NULL){
httpcCloseContext(&context);
if(newurl!=NULL) free(newurl);
return -1;
}
do {
// This download loop resizes the buffer as data is read.
ret = httpcDownloadData(&context, buf+size, 0x1000, &readsize);
size += readsize;
if (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING){
lastbuf = buf; // Save the old pointer, in case realloc() fails.
buf = realloc(buf, size + 0x1000);
if(buf==NULL){
httpcCloseContext(&context);
free(lastbuf);
if(newurl!=NULL) free(newurl);
return -1;
}
}
} while (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING);
if(ret!=0){
httpcCloseContext(&context);
if(newurl!=NULL) free(newurl);
free(buf);
return -1;
}
// Resize the buffer back down to our actual final size
lastbuf = buf;
buf = realloc(buf, size);
if(buf==NULL){ // realloc() failed.
httpcCloseContext(&context);
free(lastbuf);
if(newurl!=NULL) free(newurl);
return -1;
}
printf("response size: %" PRIx32 "\n",size);
// Print result
printf((char*)buf);
printf("\n");
gfxFlushBuffers();
gfxSwapBuffers();
httpcCloseContext(&context);
free(buf);
if (newurl!=NULL) free(newurl);
return 0;
}
int main()
{
Result ret=0;
gfxInitDefault();
httpcInit(4 * 1024 * 1024); // Buffer size when POST/PUT.
consoleInit(GFX_BOTTOM,NULL);
ret=http_post("http://httpbin.org/post", "{\"foo\": \"bar\"}");
printf("return from http_post: %" PRIx32 "\n",ret);
// Main loop
while (aptMainLoop())
{
gspWaitForVBlank();
hidScanInput();
// Your code goes here
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
}
// Exit services
httpcExit();
gfxExit();
return 0;
}
3ds.h
Central 3DS header.
aptMainLoop
bool aptMainLoop(void)
Main function which handles sleep mode and HOME/power buttons - call this at the beginning of every f...
consoleInit
PrintConsole * consoleInit(gfxScreen_t screen, PrintConsole *console)
Initialise the console.
gfxSwapBuffers
void gfxSwapBuffers(void)
Updates the configuration of both screens.
gfxInitDefault
void gfxInitDefault(void)
Initializes the LCD framebuffers with default parameters This is equivalent to calling:
GFX_BOTTOM
@ GFX_BOTTOM
Bottom screen.
Definition: gfx.h:27
gfxExit
void gfxExit(void)
Deinitializes and frees the LCD framebuffers.
gfxFlushBuffers
void gfxFlushBuffers(void)
Flushes the data cache for the current framebuffers.
gspWaitForVBlank
#define gspWaitForVBlank()
Waits for VBlank.
Definition: gspgpu.h:151
KEY_START
@ KEY_START
Start.
Definition: hid.h:15
hidKeysDown
u32 hidKeysDown(void)
Returns a bitmask of newly pressed buttons, this frame.
hidScanInput
void hidScanInput(void)
Scans HID for input data.
httpcGetResponseStatusCode
Result httpcGetResponseStatusCode(httpcContext *context, u32 *out)
Gets the response code of the HTTP context.
httpcBeginRequest
Result httpcBeginRequest(httpcContext *context)
Begins a HTTP request.
httpcGetResponseHeader
Result httpcGetResponseHeader(httpcContext *context, const char *name, char *value, u32 valuebuf_maxsize)
Gets a response header field from a HTTP context.
httpcGetDownloadSizeState
Result httpcGetDownloadSizeState(httpcContext *context, u32 *downloadedsize, u32 *contentsize)
Gets the download size state of a HTTP context.
httpcSetKeepAlive
Result httpcSetKeepAlive(httpcContext *context, HTTPC_KeepAlive option)
Sets Keep-Alive for the context.
httpcAddRequestHeaderField
Result httpcAddRequestHeaderField(httpcContext *context, const char *name, const char *value)
Adds a request header field to a HTTP context.
httpcInit
Result httpcInit(u32 sharedmem_size)
Initializes HTTPC. For HTTP GET the sharedmem_size can be zero. The sharedmem contains data which wil...
httpcDownloadData
Result httpcDownloadData(httpcContext *context, u8 *buffer, u32 size, u32 *downloadedsize)
Downloads data from the HTTP context into a buffer.
httpcOpenContext
Result httpcOpenContext(httpcContext *context, HTTPC_RequestMethod method, const char *url, u32 use_defaultproxy)
Opens a HTTP context.
httpcExit
void httpcExit(void)
Exits HTTPC.
httpcAddPostDataRaw
Result httpcAddPostDataRaw(httpcContext *context, const u32 *data, u32 len)
Adds a POST body to a HTTP context.
HTTPC_RESULTCODE_DOWNLOADPENDING
#define HTTPC_RESULTCODE_DOWNLOADPENDING
Result code returned when a download is pending.
Definition: httpc.h:35
httpcSetSSLOpt
Result httpcSetSSLOpt(httpcContext *context, u32 options)
Sets SSL options for the context.
httpcCloseContext
Result httpcCloseContext(httpcContext *context)
Closes a HTTP context.
httpcContext
HTTP context.
Definition: httpc.h:8
u8
uint8_t u8
would be nice if newlib had this already
Definition: types.h:21
Result
s32 Result
Function result.
Definition: types.h:42
s32
int32_t s32
32-bit signed integer
Definition: types.h:28
u32
uint32_t u32
32-bit unsigned integer
Definition: types.h:23