【C++】URLエンコードを行う



過去の記事(1,2) でlibcurlを用いたHTTPリクエストをやったけど、GETやらPOSTやらで送信したパラメータは全て半角英数字であった。 しかし、実際にはアルファベットだけでなく日本語や、文字にはならないバイナリデータなども送ることは多い。 このとき、URLに使える文字は半角英数字と一部の記号に限られているので、GET,POST(x-www-form-urlencoded形式)のパラメータに全角など使えない文字が 含まれる場合にはエスケープによるエンコードを行う必要がある。 といっても大したことでは無くて、A-Z,a-z,0-9,/,+の文字についてはそのまま、 それ以外の文字については1byte毎に%記号に続けて16進数表記で書けばよい。 というわけで、単純に文字列1つエンコードするなら以下のようになる。

プログラム

//urlencode1.cpp
#include<iostream>
#include<string>
std::string urlEncode(const std::string& str){
    std::ostringstream oss;
    for(char ch : str){
        if(
            (ch>='A' && ch<='Z')||
            (ch>='a' && ch<='z')||
            (ch>='0' && ch<='9')||
            ch=='-'  || ch=='~' ||
            ch=='_'  || ch=='.'
        ){
            oss << ch;
        }else{
            char buf[3]={0};
            sprintf(buf,"%02x",uint8_t(ch));
            oss << '%' << std::string(buf);
        }
    }
    return oss.str();
}

int main(){
    std::string str="あいうえお";
    for(char b : str){
        printf("%02x ",(uint8_t)b);
    }
    std::cout << std::endl;
    auto result=urlEncode(str);
    std::cout << result << std::endl;
    return 0;
}



実行結果

e3 81 82 e3 81 84 e3 81 86 e3 81 88 e3 81 8a 
%e3%81%82%e3%81%84%e3%81%86%e3%81%88%e3%81%8a



実際にリクエストを送る際にはたった1つの文字列ではなくて、 "パラメータ名=値"を&で繋いだものを送ることが多い。 そこで、パラメータ名と値の連想配列(std::unordered_map<std::string,std::string>)を引数にしてURLエンコードされた文字列を返す関数も作る。

プログラム

//urlencode2.cpp
#include<iostream>
#include<string>
#include<unordered_map>

using Params=std::unordered_map<std::string,std::string>;

std::string urlEncode(const std::string& str){
    //省略
}

std::string urlEncode(const Params& data){
    std::ostringstream oss;
    for(auto it=data.begin(); it!=data.end(); it++){
        if(it!=data.begin()){
            oss << "&";
        }
        oss << urlEncode(it->first)
            << '='
            << urlEncode(it->second);
    }
    return oss.str();
}

int main(){
    Params params;
    params["name"]="山田太郎";
    params["age"]="20";

    auto result1=urlEncode(params);

    auto result2=urlEncode({
        {"menu","味噌ラーメン"},
        {"price","780円"}
    });

    std::cout << result1 << std::endl;
    std::cout << result2 << std::endl;
    return 0;
}



実行結果

age=20&name=%e5%b1%b1%e7%94%b0%e5%a4%aa%e9%83%8e
price=780%e5%86%86&menu=%e5%91%b3%e5%99%8c%e3%83%a9%e3%83%bc%e3%83%a1%e3%83%b3



パラメータの順番が追加した順番と異なっているけど、何か問題が生じるかといったら自分には特に思いつかない。


#C++ 

投稿日時 : 2022/03/04 00:20