Skip to content

Instantly share code, notes, and snippets.

@cfillion
Last active March 16, 2019 06:20
Show Gist options
  • Save cfillion/03cac639bd9d02245228 to your computer and use it in GitHub Desktop.
Save cfillion/03cac639bd9d02245228 to your computer and use it in GitHub Desktop.
Simple command-line HTTP-only downloader using JNetLib
// DEPENDENCIES:
// WDL from https://cockos.com/wdl/
//
// BUILD INSTRUCTIONS:
// Windows:
// - SET WDL=path/to/WDL
// - cl /O2 /I%WDL% jnetlib_get.cpp %WDL%/WDL/jnetlib/httpget.cpp %WDL%/WDL/jnetlib/util.cpp %WDL%/WDL/jnetlib/connection.cpp %WDL%/WDL/jnetlib/asyncdns.cpp Ws2_32.lib
// - jnetlib_get.exe http://google.com/
//
// macOS & Linux
// - WDL=path/to/WDL; c++ -O2 -I$WDL jnetlib_get.cpp $WDL/WDL/jnetlib/{httpget,connection,util,asyncdns}.cpp -pthread -o jnetlib_get
// - ./jnetlib_get http://google.com/
#include <cstdio>
#include <string>
#ifdef _WIN32
# include <windows.h>
#else
# include <unistd.h>
void Sleep(const int ms) { usleep(ms * 1000); }
#endif
#include <WDL/jnetlib/jnetlib.h>
class InitSocketLib {
public:
InitSocketLib() { JNL::open_socketlib(); }
~InitSocketLib() { JNL::close_socketlib(); }
};
static void writeChunk(JNL_HTTPGet &agent, std::string *buffer)
{
const size_t dataSize = agent.bytes_available();
if(!dataSize)
return; // nothing to do
const size_t originalSize = buffer->size();
buffer->resize(originalSize + dataSize);
agent.get_bytes(&(*buffer)[originalSize], dataSize);
}
int main(int argc, char *argv[])
{
if(argc != 2) {
fprintf(stderr, "usage: %s [url]\n", argv[0]);
return 1;
}
InitSocketLib raii;
std::string contents;
const int chunkSize = 1<<14; // default value from JNetLib
JNL_HTTPGet agent(JNL_CONNECTION_AUTODNS, chunkSize);
agent.addheader("Accept: */*");
agent.addheader("User-Agent: jnetlib_get.cpp");
agent.connect(argv[1]);
// wait until the connection is closed
while(agent.run() == 0) {
if(agent.bytes_available() >= chunkSize)
writeChunk(agent, &contents);
Sleep(50);
}
const int status = agent.getreplycode();
if(status == 200) {
writeChunk(agent, &contents); // fetch the last (incomplete) chunk
printf("%s", contents.c_str());
return 0;
}
else {
fprintf(stderr, "error: (%d) %s\n", status, agent.geterrorstr());
return 1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment