nlib
misc/uri/uri.cpp

URI文字列を取り扱うサンプルです。以下のようなことを行っています。

以下がサンプルのソースコードになります。

#include "nn/nlib/Uri.h"
bool AnalyzeUri() {
// Analyzes and separates an URI string in http/https scheme.
// %-encoded strings are to be all decoded.
// Fails if URI is incorrect.
size_t i;
size_t n;
nlib_printf("\n==== AnalyzeUri ===\n");
HttpStyleUri uri;
if (nlib_is_error(uri.Parse("HTTP://www.EXAMPLE.com:8081/app/search?"
"q=nintendo&qs=n&form=QBLH&filt=all#fragment")))
return false; // URI is too long
// http or https are possible.
// the name of scheme is normalized into lower case.
nlib_printf("scheme: %s\n", uri.GetScheme());
// The hostname is normalized into lower base.
nlib_printf("host: %s\n", uri.GetHost());
// You can get the port number as an integer value.
nlib_printf("port: %d\n", uri.GetPort());
// The path is separated into the segments.
// %-encoded characters are all decoded.
// The path string is normalized, and '..' and '.' are removed.
nlib_printf("segments: [");
n = uri.GetNumSegment();
for (i = 0; i < n; ++i) {
nlib_printf("\"%s\", ", uri.GetSegment(i));
}
nlib_printf("]\n");
// The queries are stored in Key-Value manner.
// %-encoded characters are all decoded.
n = uri.GetNumQuery();
nlib_printf("query: {");
for (i = 0; i < n; ++i) {
nlib_printf("\"%s\":\"%s\", ", uri.GetQueryKeyValue(i)->first,
uri.GetQueryKeyValue(i)->second);
}
nlib_printf("}\n");
// The fragments are not separated.
// %-encoded characters are all decoded.
nlib_printf("fragment: %s\n", uri.GetFragment());
return true;
}
bool ComposeUri() {
// Compose an URI string.
nlib_printf("\n==== ComposeUri ===\n");
HttpStyleUri uri;
// Hostname does not include '/'.
if (nlib_is_error(uri.SetHost("www.example.com")))
return false; // Fails if it has incorrect characters or etc.
// You have to speficy the absolute path.
if (nlib_is_error(uri.SetPath("/app/search")))
return false; // Fails if it has incorrect characters or etc.
// Sets the queries one by one here.
// You can also use uri.SetQuery() to set the queries all together.
if (nlib_is_error(uri.AddQuery("q", "nintendo"))) return false;
if (nlib_is_error(uri.AddQuery("qa", "n"))) return false;
if (nlib_is_error(uri.AddQuery("form", "QBLH"))) return false;
if (nlib_is_error(uri.AddQuery("filt", "all"))) return false;
// Set the fragments.
if (nlib_is_error(uri.SetFragment("fragment"))) return false;
// Composes an URI string.
// %-encoding is performed if needed.
char uriText[2048];
if (!uri.ComposeString(uriText))
return false; // Fails if the buffer is insufficient or etc.
nlib_printf("%s\n", uriText);
return true;
}
bool RelativePath() {
// Resolves the relative path.
// The base URI is:
// http://example.com/news/index.html?ref=mynews/test
// And resolves the relative path '../js/mylib.js'.
nlib_printf("\n=== RelativePath ===\n");
const char base[] = "http://example.com/news/index.html?ref=mynews/test";
const char relative[] = "../js/mylib.js";
nlib_printf("base: %s\n", base);
nlib_printf("relative: %s\n", relative);
// You have to use Uri class for relative paths.
Uri relativeUri;
Uri baseUri, resultUri;
if (nlib_is_error(baseUri.Parse(base))) return false;
if (nlib_is_error(relativeUri.Parse(relative))) return false;
if (nlib_is_error(resultUri.AddBaseUri(relativeUri, baseUri))) return false;
char uriText[2048];
if (nlib_is_error(resultUri.ComposeString(uriText)))
return false; // Fails if the buffer is insufficient or etc.
nlib_printf("result: %s\n", uriText);
return true;
}
bool UseUriTemplate() {
UriTemplate templ;
char str[1024];
nlib_printf("\n==== URI Template ===\n");
// You should read RFC6570 about URI Template.
nlib_printf("Template: 'http://example.com/map?{x,y}#{x,hello,y,undef,empty}'\n");
e = templ.SetTemplate("http://example.com/map?{x,y}#{x,hello,y,undef,empty}");
if (nlib_is_error(e)) return false;
// Sets parameters.
nlib_printf(" var = 'value'\n");
e = templ.SetParameter("var", "value");
if (nlib_is_error(e)) return false;
nlib_printf(" hello = 'Hello World!'\n");
e = templ.SetParameter("hello", "Hello World!");
if (nlib_is_error(e)) return false;
nlib_printf(" empty = ''\n");
e = templ.SetParameter("empty", "");
if (nlib_is_error(e)) return false;
nlib_printf(" path = '/foo/bar'\n");
e = templ.SetParameter("path", "/foo/bar");
if (nlib_is_error(e)) return false;
nlib_printf(" x = '1024'\n");
e = templ.SetParameter("x", "1024");
if (nlib_is_error(e)) return false;
nlib_printf(" y = '768'\n");
e = templ.SetParameter("y", "768");
if (nlib_is_error(e)) return false;
if (nlib_is_error(templ.Resolve(NULL, str))) return false;
nlib_printf("Resolved: '%s'\n", str);
return true;
}
bool SampleMain(int, char**) {
return AnalyzeUri() && ComposeUri() && RelativePath() && UseUriTemplate();
}
NLIB_MAINFUNC