Zig Requires Chilkat v11.0.0+
Zig
REST Follow Redirects
See more REST Examples
Demonstrates how to follow a 302/303 redirect response.Chilkat Zig Downloads
const std = @import("std");
const chilkat = @import("chilkat");
pub fn main(init: std.process.Init) !void {
const alloc = init.arena.allocator();
// This example requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
const rest = try chilkat.Rest.init();
defer rest.deinit();
const b_tls = true;
const port = 443;
const b_auto_reconnect = true;
rest.connect("chilkatsoft.com", port, b_tls, b_auto_reconnect) catch {
std.debug.print("{s}\n", .{try rest.getLastErrorText(alloc)});
return;
};
// Send a POST to a URL that will respond with a 302 redirect..
rest.addQueryParam("firstName", "John") catch {};
rest.addQueryParam("lastName", "Doe") catch {};
var response_text: [:0]const u8 = rest.fullRequestFormUrlEncoded(alloc, "POST", "/echoPost302.asp") catch {
std.debug.print("{s}\n", .{try rest.getLastErrorText(alloc)});
return;
};
const status_code = rest.getResponseStatusCode();
// Examine the response status code
if (status_code < 300) {
std.debug.print("Not a redirect.\n", .{});
std.debug.print("{s}\n", .{response_text});
return;
}
if (status_code > 399) {
std.debug.print("Error response: Status code = {d}\n", .{status_code});
std.debug.print("{s}\n", .{response_text});
return;
}
std.debug.print("Redirect status code = {d}\n", .{status_code});
// The response header will contain a Location field with the redirect URL, such as this:
// Location: http://www.chilkatsoft.com/echoPostFinal.asp
// The response status code determines how the client should behave.
// Here are some common possibilities:
// 301: Moved Permanently
// This and all future requests should be directed to the given URI. (Keep the original HTTP method for the redirect. In this case, the
// original request was a POST, so we POST to the redirect URL.)
// 302: Found (aka Object Moved aka Moved Temporarily)
// This is the most popular redirect code, but also an example of industrial practice contradicting the standard. HTTP/1.0 specification (RFC 1945 ) required the client
// to perform a temporary redirect (the original describing phrase was �Moved Temporarily�), but popular browsers implemented it as a 303 See Other. Therefore, HTTP/1.1
// added status codes 303 and 307 to disambiguate between the two behaviors. However, the majority of Web applications and frameworks still use the 302 status code
// as if it were the 303.
// 303: See Other
// The response to the request can be found under another URI using a GET method. When received in response to a PUT, it should be assumed that the server has
// received the data and the redirect should be issued with a separate GET message.
// 307: Temporary Redirect
// In this occasion, the request should be repeated with another URI, but future requests can still use the original URI. In contrast to 303, the request method
// should not be changed when reissuing the original request. For instance, a POST request must be repeated using another POST request.
std.debug.print("{s}\n", .{try rest.getResponseHeader(alloc)});
// Get the redirect URL
const url_str = try rest.getLastRedirectUrl(alloc);
if (!rest.getLastMethodSuccess()) {
std.debug.print("No Location header found for redirect.\n", .{});
return;
}
const redirect_url = try chilkat.Url.init();
defer redirect_url.deinit();
redirect_url.parseUrl(url_str) catch {};
// Prep for the redirect..
rest.clearAllParts() catch {};
// Disconnect and re-connect.
// (This can be skipped if both the host and SSL/TLS conditions are the same.)
rest.disconnect(100) catch {};
rest.connect(try redirect_url.getHost(alloc), redirect_url.getPort(), redirect_url.getSsl(), b_auto_reconnect) catch {
std.debug.print("{s}\n", .{try rest.getLastErrorText(alloc)});
return;
};
if ((status_code == 301) or (status_code == 307)) {
// Redirect using a POST, sending the same params to the new destination
rest.addQueryParam("firstName", "John") catch {};
rest.addQueryParam("lastName", "Doe") catch {};
response_text = rest.fullRequestFormUrlEncoded(alloc, "POST", try redirect_url.getPath(alloc)) catch {
std.debug.print("{s}\n", .{try rest.getLastErrorText(alloc)});
return;
};
}
if ((status_code == 302) or (status_code == 303)) {
// Redirect using a GET, sending the query params found in the redirect URL.
response_text = rest.fullRequestFormUrlEncoded(alloc, "GET", try redirect_url.getPathWithQueryParams(alloc)) catch {
std.debug.print("{s}\n", .{try rest.getLastErrorText(alloc)});
return;
};
}
// Show the final status code and the response text.
std.debug.print("Final status code = {d}\n", .{rest.getResponseStatusCode()});
std.debug.print("Final response text (HTML, XML, JSON, or whatever..)\n", .{});
std.debug.print("{s}\n", .{response_text});
}