Thalassa CMS logo

Thalassa CMS

POST requests (handling web forms)

Pages accepting POST requests

Thalassa CGI has built-in support for several webforms, or, strictly speaking, for several fixed sets of parameters sent with a POST request. With the exception of command=setcookie case, all other forms are handled in a unified manner. To handle a form, a page must be configured; each of the configured pages (actually, [page ] ini sections, including these multipath ones) may either handle one of the predefined forms, or none of them.

A page intended to handle a form must have the post_allowed parameter set to yes. In most cases the page should also have a non-empty value for the action parameter. This is not a requirement, so you can have a page that accepts POST requests but does nothing, only shows some HTML; using macros, primarily the %[req:param: ] macro function, a lot of things can be done, but it is all about generating the HTML response, not actually performing anything.

Please note all configured pages also accept GET requests, and there's no way to tell the CGI not to accept them. In most cases it is convenient to show the user the corresponding web form when the page intended to handle it is requested with the GET method. If, however, you for any reason decide otherwise, it is still possible to use conditional macros and the %[req:method] function just to tell the user (s)he shouldn't have reached this page in this way.

What actions are supported

The action parameter's value must consist of the action name and arguments, much like a command line; there's a fixed set of action names supported by the CGI program, each of them expects a fixed set of form input values. In the present version, the following actions are supported:

Only feedback, comment_add and comment_edit accept arguments; for example, “feedback techsupport” as the action parameter's value means a feedback category “techsupport” must be preselected in the feedback web form. For the rest of actions, the action value consists of only one word — the action name itself. Later on, we'll document each of the actions together with their arguments, if any, and the web form parameters they accept.

Handling a POST request's result

Once a POST request is received, the CGI first performs whatever actions are requested, and only then generates and sends back the response page. So, at the time of the HTML generation, it is already known what has just been done and was it successful or not. This result obviously should be communicated to the user somehow.

From the Thalassa CGI's point of view, the action result consists of two things: a message and a boolean value that reflects whether the requested action successfully done.

There's one important thing to take into account. Even when you expect your page to be displayed as a response for a GET request, but the page is configured to require an active session, it can end up being displayed as a result of a set-cookie POST request. In this case the request is known to be successful, otherwise the user would see the Retry Captcha special page instead; however, you should be prepared to this. For instance, you should check for presence of a message and include it in your page in case it is there, even if your page is not intended to handle POST requests at all — but nonetheless requires the session to be established.

And, well, don't be too surprized if the %[req:method] returns “POST” on a page configured as POST-uncapable. If it requires an active session, you now know why such strange things happen sometime.

The messages

There's a fixed set of messages; the CGI program identifies them with names, hopefully self-descriptive, such as new_values_saved or comment_deleted. The particular wording for each of the messages is configurable; furthermore, in the present version there are no defaults for them, so one must configure all messages. To do so, the [message] ini section is used; every parameter in this section has a name that corresponds to a message name, and the value is the actual text of the message. Here's an example of the section with values for all messages used by Thalassa CGI; certainly you can choose your own wording or translate the messages to another language, but this example is nonetheless useful:

  [message]
  server_side_error = Server side error.  Please report this
      to the site owner.
  cookie_set = Cookie has been set, session established.
      The interactive features of the site are now available to you.
  cookie_removed = Session closed, cookie removed.
  field_not_filled = Some of mandatory fields are not filled in.
  logged_in = Logged in successfully.
  wrong_login_password = Wrong user id or password.
  login_unknown = User id unknown.
  invalid_login_name = The user id is not acceptable.
      Please choose another user id.
  login_not_available = The user id already exists or blocked.
      Please choose another user id.
  pass_req_too_early = You still have some passwords left and
      less than 24 hours passed since they were sent.
      Please try again later.
  invalid_email_address = Invalid format of email address.
  email_already_used = This email address is user by an existing
      user of the site.  If you forgot your user id, please contact
      the site administrators.
  email_belonged_to_other = This email address was once confirmed
      to belong to another user.  The system doesn't allow to
      change ownership of emails; if you've got a reason for it,
      please contact the site administration.
  email_recently_tried = Someone recently tried to register a user
      using this email, but didn't confirm it.  To prevent flooding
      of innocent mailboxes, the site blocks repeated registration
      messages to the same address for a certain time.
  email_banned = This address or its domain name is on the
      stop-list.
  changemail_too_early = Recently you already requested to change
      your address.  Please try again later.
  changemail_canceled = Email change request cancelled.
  invalid_feedback_category = The given feedback category is not
      configured.  Please report this error to the site owner.
  email_sent_to_you = Message to your email address
      successfully sent.
  your_email_sent = Your email successfully sent.
  error_sending_email = Error sending email.
      Sorry for the inconvenience.
  new_values_saved = New values saved.
  email_changed = Your email address changed.
  wrong_confirmation_code = Wrong confirmation code.
  not_really_confirm = Not confirmed.  To confirm the request
      you need to enter the word <em>really</em>
      into the confirmation input field.
  comment_deleted = Comment deleted.
  comment_queued_for_premod = Your comment has been queued
      for moderation.
  comment_saved = Comment submitted.
  page_regenerated = Page regenerated.
  not_logged_in = Logged in users only.
  not_this_way = This doesn't work this way :-)
  permission_denied = Permission denied.
  anon_denied = Anonymous users are not allowed to do this.
  not_implemented_yet = The feature is not implemented yet.
  bug_in_the_code = There's a bug in the site's implementation.
      Please report this to the site's owner.

The exact situations when each of the messages is used will be explained together with their respective actions.

Macros accessing action result

A handful of macros is used to access a POST request status. The %message% expands to the POST result message, as configured in the [message] section, if such message exists; otherwise (e.g. if the page is being generated in response to a GET request, not POST), the macro returns an empty string.

The ifmessage, ifmessageok, ifactresult and ifactresultok macros are condition checkers; they all accept exactly two arguments, the then value and the else value, and return the former in case the condition is true and the latter if it is false.

For the %[ifmessage: ] macro, the condition being checked is whether there's a message, that is, would the %message% return a non-empty string if we call it.

The %[ifmessageok: ] macro checks whether the result is present and it is a success.

The %[ifactresult: ] macro checks whether we have a result of the action configured for this page. This is different from the question if we've got a message in that in case we're composing the page as a result of successful passing of the CAPTCHA and establishing the session. If it is a CAPTCHA success, then the ifmessage's (and even the ifmessageok's) condition is true, but the ifactresult's condition is false.

The %[ifactresultok: ] macro's condition is if there's an action result (as for the ifactresult macro) and it is successful.

For example, your template for the page which accepts POST requests may include something like this:

  %[ifmessage:<div
    class="msgbox_%[ifmessageok:ok:err]">%message%</div>]

— while your CSS can have the respective classes, like this:

  .msgbox_ok {
    border: 2px solid #00b000;
    margin: auto;
    width: 75%;
  }
  .msgbox_err {
    border: 2px solid #b00000;
    margin: auto;
    width: 75%;
  }

Session removal action

The rmsession action is perhaps the simplest one among actions supported by Thalassa CGI, but it can serve as a good example on how all the machinery works. The action doesn't accept any arguments, and, furthermore, it doesn't need any parameters from the webform that sends the POST request. This effectively means the form may consist of the submit button only; its duty is to form an (empty!) POST request directed to the desired page — the one you use for the rmsession action.

Let's name the page /rmspage. In a real life situation you might want to name it more intuitively, like /remore_session, /close_session or even just /rmsession, it is still okay, but in our example it is better to make the action name and the page name differ — just to avoid confusion. So, the page is available at /rmspage under the path to your CGI; we don't assume any particular location for the CGI, instead we just use the path we were called through, which is available as %[req:script]. The web form that removes the session and the cookie may then look like this:

  <form name="rmform" action="%[req:script]/rmspage" method="POST">
  <input type="submit" value="Close your session" />
  </form>

Note that the form name (rmform in this example) doesn't matter anything special, you can name it whatever you want. Also, you can place this form on any of the pages your CGI generates, or even on all of them. It may be useful to check whether the session actually exist and only display the form if it does. It is also possible to place the form on any of your static pages, but this is not recommended, because, first, you'll be unable to use the %[req:script] macro which is CGI-specific, so you'll have to mention the full URI explicitly, and, second, on static pages you can't check anything so your visitors will see the form even when they don't have any sessions.

The /rmspage page configuration can then look like this:

  [page /rmspage]
  session_required = no
  embedded = no
  post_allowed = yes
  action = rmsession
  template = %html:header%
  +%[ifmessage:<div
  +   class="msgbox_%[ifmessageok:ok:err]">%message%</div>]
  +%[sess|ifvalid|<p>Session is active</p>
  +  <form name="rmform" action="%[req:script]/rmspage" method="POST">
  +  <input type="submit" value="Close your session" />
  +  </form>
  +   |
  +  <p>Cookie is not set, no session</p>
  +]
  +%html:footer%

In this example we placed the cookie removal request form on the same page, so that if the browser is directed to the page (that is, to the URI like /thalcgi.cgi/rmspage) with a usual GET request (that is, with a regular link, not a web form), the user will see the Close your session button if there's a session, and the message Cookie is not set, no session otherwise. For the case of a POST request, the user will see the message box at the top of the page, which will either say that the cookie has just been successfully removed, or that there's no cookie and no session to close. In both cases, the page itself (under the message box) will consist of a single paragraph saying Cookie is not set, no session; this is because the cookie either didn't exist, or has been removed, anyways there's no cookie here and now.

© Andrey V. Stolyarov, 2023, 2024