I know this is an old question but I am attempting to implement an HTCPCP server and I have also found that the RFC is contradictory, incomplete or seemingly inaccurate in some areas. After wrestling with the RFC I think the appropriate way to structure your request using curl is:
curl 'theserver.com` \
--request 'BREW' \
--header 'Scheme: coffee' \
--header 'Content-Type: message/coffeepot' \
--header 'Accept-Additions: milk-type/Cream, syrup-type/Vanilla' \
--data 'coffee-message-body=start'
The above syntax may or may not line up with the implementation on the server you are (were?) attempting to interact with but I've explained my reasoning below.
Rationale
It is clear from section 2 and section 3 of RFC2324 that a valid HTCPCP URL should start with the coffee:
scheme, not with https:
.
The scheme in section 3 is a simplified version of the General Syntax of URI's from RFC2068 and seems to restrict HTCPCP to only accept the net-path
form of URIs; "//" followed by a network location. Local paths (like file:/
paths in HTTP) are not allowed. Therefore, to make a request to an HTCPCP server at theserver.com
, the URL must start with coffee://theserver.com
(or an internationalised equivalent such as koffie://theserver.com
for Afrikaans/Dutch).
That being said, curl does not allow you to specify an arbitrary scheme so I moved it into its own HTTP 'Scheme' Header which comes out as HTTP_SCHEME in Rack. On my server, I manually change the url_scheme to the HTTP_SCHEME value if HTTP_SCHEME is set.
The next part of the URI is optional unless there is more than one pot. For a server with multiple pots you need to append /pot-#
where # is the pot number. Assuming zero-indexed pots, the second pot would be accessible at coffee://theserver.com/pot-1
.
The final (also optional) part of the URI is the additions. The RFC does not provide examples (and section 3 may contradict section 2.2.2.1) but the the way I read section 3 is that addition requests should be passed as parameter/value pairs appended to the URL. If so, your requested milk type of cream and syrup type of vanilla would mean the correct additions-list
string on the end of the URL is milk-type=Cream&syrup-type=Vanilla
.
Combining all that together the final URL (assuming the HTCPCP server doesn't have multiple pots available) is theserver.com?milk-type=Cream&syrup-type=Vanilla
If multiple pots are available, the second pot at that address (again assuming pots are zero-indexed) would be theserver.com/pot-1?milk-type=Cream&syrup-type=Vanilla
The downside to this approach, and perhaps the reason that section 2.2.2.1 exists, is that it doesn't seem to allow for substitute additions. If my first choice of milk is Cream but I'd also be happy with Whole-milk, how do I specify (and prioritise) that using parameter/value pairs?
A logical answer to me is that we request our desired additions in the URL but we include acceptable additions (including any allowed substitutions) using the Accept-Additions
header. Then again, a properly crafted Accept-Additions
header renders the additions in the URL completely redundant. In my implementation I think I will return a 400 Bad Request
error if the additions-list is present in the URL but clashes with the accepted additions in the header.
Once again, the instructions in the RFC on how to set this header seems to have typographical errors and it lacks examples but given it seems to be closely modelled on 2068 (and explicitly mentions the Accept
request-header field), I think the intention is to copy the accept-params
prioritisation system from 2068.
Let's say I like white coffee, the more fat the better, but I'd rather have black coffee than ingest soy, rice, or almond "milk". In that case my milk-type preferences might be:
- Cream
- Whole-milk
- Half-and-half, Part-skim or Skim
- No milk
To indicate this using 2068 quality values syntax, the header could be:
Accept-Additions: milk-type/Cream,
milk-type/Skim; q=0.5,
milk-type/none; q=0.25,
milk-type/Whole-milk; q=0.75,
milk-type/Half-and-half; q=0.5,
milk-type/Part-skim; q=0.5
The order is irrelevant as the preference comes from the qvalues. Note well I've borrowed the all lowercase none
value/syntax from the Accept-Ranges
header of the HTTP spec.
In your case, if you only want a vanilla coffee with cream, I suspect the header should be:
Accept-Additions: milk-type/Cream, syrup-type/Vanilla
Regarding the contradictory statements about media type, section 4 specifically deals with Media Type whereas section 2.1.1 only mentions it as an aside. Furthermore, the language in section 4 is stronger than section 2.1.1 so the appropriate media type is therefore message/coffeepot
.
It should also be noted that the BREW
method is preferred to POST
and the body needs to contain coffee-message-body = "start" | "stop"
so the final curl command that combines all those pieces and starts brewing a vanilla coffee with cream (accepting no substitutes) would be:
curl 'theserver.com?milk-type=Cream&syrup-type=Vanilla` \
-X 'BREW' \
-H 'Scheme: coffee' \
-H 'Content-Type: message/coffeepot' \
-H 'Accept-Additions: milk-type/Cream, syrup-type/Vanilla' \
-d 'coffee-message-body=start'
If you agree that the additions-list
in the URL is redundant, the command (this time using -- parameters for curl) would be:
curl 'theserver.com` \
--request 'BREW' \
--header 'Scheme: coffee' \
--header 'Content-Type: message/coffeepot' \
--header 'Accept-Additions: milk-type/Cream, syrup-type/Vanilla' \
--data 'coffee-message-body=start'
Hopefully you'll get back a 2xx return code and the coffee will start brewing. If Cream or Vanilla aren't available you should get back a 406 Not Acceptable
return code and the body of the response should contain the currently available additions.