nlib
misc/uri/uri.cpp

This sample demonstrates the handling of URI strings. It performs the following operations.

The source code of the sample is shown below.

/*--------------------------------------------------------------------------------*
Project: CrossRoad
Copyright (C)Nintendo All rights reserved.
These coded instructions, statements, and computer programs contain proprietary
information of Nintendo and/or its licensed developers and are protected by
national and international copyright laws. They may not be disclosed to third
parties or copied or duplicated in any form, in whole or in part, without the
prior written consent of Nintendo.
The content herein is highly confidential and should be handled accordingly.
*--------------------------------------------------------------------------------*/
#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.
nlib_printf("\n==== AnalyzeUri ===\n");
Uri 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.GetPortNumber());
size_t path_strlen;
char path[512];
if (nlib_is_error(Uri::DecodePath(&path_strlen, path, uri.GetPath()))) {
return false;
}
nlib_printf("path: %s\n", path);
UriQueryDecoder<> decoder;
if (nlib_is_error(decoder.Init(uri))) return false;
nlib_printf("query: {");
while (decoder.HasNext()) {
std::pair<errno_t, const char*> k = decoder.GetKey();
std::pair<errno_t, const char*> v = decoder.GetValue();
if (k.first != 0 || v.first != 0) return false;
nlib_printf("\"%s\":\"%s\", ", k.second, v.second);
decoder.MoveNext();
}
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");
Uri uri;
if (nlib_is_error(uri.SetScheme("http")))
return false;
// 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.
UriQueryEncoder<> encoder;
(void)encoder.Append("q", "nintendo");
(void)encoder.Append("qa", "n");
(void)encoder.Append("form", "QBLH");
(void)encoder.Append("filt", "all");
if (nlib_is_error(uri.SetQuery(encoder))) 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 relative_uri;
Uri base_uri, result_uri;
if (nlib_is_error(base_uri.Parse(base))) return false;
if (nlib_is_error(relative_uri.Parse(relative))) return false;
if (nlib_is_error(result_uri.AddBaseUri(relative_uri, base_uri))) return false;
char uriText[2048];
if (nlib_is_error(result_uri.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