Set-Cookie(Expires)

Expires属性を付けることで、Cookieの期限時刻を設定できる。

HTTP Cookie の使用 - HTTP | MDN
Set-Cookie - HTTP | MDN

期限時刻を過ぎると、ブラウザのリクエストからクッキーが削除される。

/* アクセプトループ */
int accept_loop(int soc){

  /* 変数の宣言と初期化. */
  struct sockaddr_in client_addr; /* クライアントアドレスclient_addr */
  int client_addr_len; /* client_addrの長さclient_addr_len. */
  int acc; /* アクセプトソケットacc */
  char *client_ip_addr_str; /* クライアントのIPアドレス文字列へのポインタclient_ip_addr_str. */
  u_short client_port; /* クライアントのポート番号client_port. */
  int ret = 0; /* ループ抜ける時の理由ret. */
  char recv_buf[4096] = {0}; /* recv_buf(長さ4096)を{0}で初期化. */
  char send_buf[4096] = {0}; /* send_buf(長さ4096)を{0}で初期化. */
  char response_header[4096] = {0}; /* response_header(長さ4096)を{0}で初期化. */
  char response_body[4096] = {0}; /* response_body(長さ4096)を{0}で初期化. */
  time_t t; /* 現在のUNIX時間t. */
  struct tm *tm_ptr; /* tm構造体へのポインタtm_ptr. */
  char time_str[128]; /* 時刻文字列time_str. */
  int content_length = 0; /* Content-Lengthの値を0で初期化. */
  char content_length_str[128]; /* Content-Lengthの値を文字列にしたものcontent_length_str. */
  time_t expires_t; /* 期限時間expires_t. */
  struct tm *expires_tm_ptr; /* 期限時間構造体へのポインタexpires_tm_ptr. */
  char expires_time_str[128]; /* 期限時間文字列expires_time_str. */

  /* 終わるまでループ. */
  while (1){ /* 無限ループ. */

    /* アクセプト処理 */
    client_addr_len = sizeof(client_addr); /* サイズ取得 */
    acc = accept(soc, (struct sockaddr *)&client_addr, &client_addr_len); /* acceptでaccやclient_addrを取得. */
    if (acc < 0){ /* 0未満は終了. */
      perror("accept"); /* "accept"エラー. */
      ret = -1; /* "accept"エラーはretが-1. */
      break; /* ループから抜ける. */
    }

    /* クライアント情報の表示 */
    client_ip_addr_str = inet_ntoa(client_addr.sin_addr); /* inet_ntoaでクライアントのclient_addr.sin_addrをIPアドレス文字列に変換. */
    client_port = ntohs(client_addr.sin_port); /* ntohsでクライアントのclient_addr.sin_portを符号なし10進整数のポート番号に変換. */
    printf("accept!(IPAddress = %s, Port = %hu)\n", client_ip_addr_str, client_port); /* IPアドレスとポートを表示. */

    /* 読み込み */
    memset(recv_buf, 0, sizeof(char) * 4096); /* recv_bufをクリア. */
    recv(acc, recv_buf, sizeof(recv_buf), 0); /* recvでaccから読み込み, recv_bufに格納. */
    printf("----- recv begin -----\n"); /* recv beginフォームを出力. */
    printf("%s\n", recv_buf); /* recv_bufを出力. */
    printf("----- recv end -----\n"); /* recv endフォームを出力. */

    /* 現在時刻文字列の作成. */
    t = time(NULL); /* timeでtを取得. */
    tm_ptr = gmtime(&t); /* gmtimeでtm_ptrを取得. */
    strftime(time_str, sizeof(time_str), "%Y/%m/%d %H:%M:%S %Z", tm_ptr); /* strftimeでtime_str作成. */

    /* 期限時刻文字列の作成. */
    expires_t = t + 5 * 60; /* 5分. */
    expires_tm_ptr = gmtime(&expires_t); /* expires_tm_ptrを取得. */
    strftime(expires_time_str, sizeof(expires_time_str), "%a, %d %b %Y %H:%M:%S %Z", expires_tm_ptr); /* strftimeでexpires_time_str作成. */

    /* レスポンスボディの作成. */
    strcpy(response_body, "<html>\r\n"); /* response_bodyに"<hmtl>\r\n"をコピー. */
    strcat(response_body, "  <head>\r\n"); /* response_bodyに"  <head>\r\n"を連結. */
    strcat(response_body, "    <title>Content-Type</title>\r\n"); /* response_bodyに"    <title>Content-Type</title>\r\n"を連結. */
    strcat(response_body, "  </head>\r\n"); /* response_bodyに"  </head>\r\n"を連結. */
    strcat(response_body, "  <body>\r\n"); /* response_bodyに"  <body>\r\n"を連結. */
    strcat(response_body, "    "); /* response_bodyに"    "を連結. */
    strcat(response_body, time_str); /* response_bodyにtime_strを連結. */
    strcat(response_body, "\r\n"); /* response_bodyに"\r\n"を連結. */
    strcat(response_body, "  </body>\r\n"); /* response_bodyに"  </body>\r\n"を連結. */
    strcat(response_body, "</html>\r\n"); /* response_bodyに"</html>\r\n"を連結. */

    /* レスポンスヘッダの作成. */
    strcpy(response_header, "HTTP/1.0 200 OK\r\n"); /* response_headerに"HTTP/1.0 200 OK\r\n"をコピー. */
    strcat(response_header, "Content-Length: "); /* response_headerに"Content-Length: "を連結. */
    content_length = strlen(response_body); /* response_bodyの長さをstrlenで取得し, content_lengthに格納. */
    sprintf(content_length_str, "%d", content_length); /* sprintfでcontent_lengthを文字列content_length_strに変換. */
    strcat(response_header, content_length_str); /* response_headerにcontent_length_strを連結. */
    strcat(response_header, "\r\n"); /* response_headerに"\r\n"を連結. */
    strcat(response_header, "Content-Type: text/html\r\n"); /* response_headerに"Content-Type: text/html\r\n"を連結. */
    strcat(response_header, "Set-Cookie: key1=value1"); /* response_headerに"Set-Cookie: key1=value1"を連結. */
    strcat(response_header, "; Expires="); /* response_headerに"; Expires="を連結. */
    strcat(response_header, expires_time_str); /* response_headerにexpires_time_strを連結. */
    strcat(response_header, ";\r\n"); /* response_headerに";\r\n"を連結. */ 

    /* レスポンスの送信. */
    strcpy(send_buf, response_header); /* send_bufにresponse_headerをコピー. */
    strcat(send_buf, "\r\n"); /* send_bufに"\r\n"を連結. */
    strcat(send_buf, response_body); /* send_bufにresponse_bodyを連結. */
    send(acc, send_buf, strlen(send_buf), 0); /* send_bufを送信. */

    /* アクセプトしたクライアントソケットファイルディスクリプタを閉じる. */
    close(acc); /* closeでaccを閉じる. */

  }

  /* retを返す. */
  return ret; /* retを返して終了. */

}

現在時刻から5分後をExpiresとする。

この時刻にアクセスしたとする
この時刻にアクセスしたとする

この時刻にアクセスしたとする。

Set-Cookieの部分はもう外していい。

5分以内はアクセスしても
5分以内はアクセスしても

5分以内はアクセスしても、

リクエストにクッキーが付く
リクエストにクッキーが付く

リクエストにクッキーが付く。

5分過ぎると、
5分過ぎると、

5分過ぎると、

クッキーはもう付いていない
クッキーはもう付いていない

クッキーはもう付いていない。

Sample/http/Set-Cookie/Expires/src/Set-Cookie at master · bg1bgst333/Sample · GitHub