Re: URI construction for REST API and use of verbs as resource?

"Nicholas Shanks [email protected] [rest-discuss]" <[email protected]> Wed, 11 Nov 2015 15:38:10 +0000
Newsgroups gmane.comp.web.services.rest
Message-ID <CA+hEJVVM4NYpmXrqYVz2or4TFeaSmxVxDNCekxESdMTSO+D61g@mail.gmail.com>
--089e013a06bc6cb1910524459f6f
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On 17 June 2015 at 14:52, Jeff Lowe [email protected] [rest-discuss] <
[email protected]> wrote:


> I struggled with this for a while for a particular use case. My API neede=
d
> to support the releasing of a customer-order to manufacturing. That
> suggested the URL ../orders/{id}/release.
>
>
>
> However I was entertaining that =E2=80=9Cverbs are RPC and resources are =
REST=E2=80=9D,
> and =E2=80=9Crelease=E2=80=9D is obviously a verb. I entertained a few di=
fferent approaches:
>
> 1.      PUT an order resource and set the =E2=80=9Cstate=E2=80=9D to rele=
ased. That
> didn=E2=80=99t seem right because =E2=80=9Crelease=E2=80=9D is more of a =
business process than a
> property on a resource. In addition I=E2=80=99d be exposing internal stat=
e that
> shouldn=E2=80=99t necessarily be exposed.
>

This is the correct way to do it. Any change of state is a 'process' even
if all it takes is flipping a bit in a database.
REST asks that you provide the *desired state* of a resource (URL) and the
server is responsible for transitioning from whatever state it is in
currently to the desired state.

For example a simple issue in an issue-tracker has a field with four
values: reported, open, and closed. The verbs "accept" and "re-open" would
both be used in natural language to describe the transitions to "open" from
the other two states, but a RESTful API would only allow the user to state
the end value for the field, "open", and it would be up to the server to
transition from either reported or closed as appropriate (or do nothing if
it was already open).


> 2.      POST to an order-releaser resource. That=E2=80=99s more restful, =
but
> seems artificial.
>

This is not RESTful, it's RPC.

--=20
Nicholas.

--089e013a06bc6cb1910524459f6f
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable




<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/htm=
l4/strict.dtd">
<html>
<head>
</head>






=20
<body style=3D"background-color: #fff;">
<span style=3D"display:none">&nbsp;</span>

<!--~-|**|PrettyHtmlStartT|**|-~-->
<div id=3D"ygrp-mlmsg" style=3D"position:relative;">
  <div id=3D"ygrp-msg" style=3D"z-index: 1;">
<!--~-|**|PrettyHtmlEndT|**|-~-->

    <div id=3D"ygrp-text" >
=20=20=20=20=20=20
=20=20=20=20=20=20
      <p><div dir=3D"ltr">On 17 June 2015 at 14:52, Jeff Lowe <a href=3D"ma=
ilto:[email protected]">[email protected]</a> [rest-discuss] <span di=
r=3D"ltr">&lt;<a href=3D"mailto:[email protected]" targe=
t=3D"_blank">[email protected]</a>&gt;</span> wrote:<div=
 class=3D"gmail_extra"><div class=3D"gmail_quote"><div>=C2=A0</div><blockqu=
ote class=3D"gmail_quote" style=3D"border-left:1px #ccc solid;"><div style=
=3D"background-color:#fff;"><div><div><div><div><p class=3D"MsoNormal"><spa=
n style=3D"font-size:11.0pt;color:#1f497d;">I struggled with this for a whi=
le for a particular use case. My API needed to support the releasing of a c=
ustomer-order to manufacturing. That suggested the
 URL ../orders/{id}/release.<u></u><u></u></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;color:#1f497d;"><u><=
/u>=C2=A0<u></u></span></p>
<p class=3D"MsoNormal"><span style=3D"font-size:11.0pt;color:#1f497d;">Howe=
ver I was entertaining that =E2=80=9Cverbs are RPC and resources are REST=
=E2=80=9D, and =E2=80=9Crelease=E2=80=9D is obviously a verb. I entertained=
 a few different approaches:<u></u><u></u></span></p>
<p><u></u><span style=3D"font-size:11.0pt;color:#1f497d;"><span>1.<span sty=
le=3D"font:7.0pt &quot;Times New Roman&quot;;">=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0
</span></span></span><u></u><span style=3D"font-size:11.0pt;color:#1f497d;"=
>PUT an order resource and set the =E2=80=9Cstate=E2=80=9D to released. Tha=
t didn=E2=80=99t seem right because =E2=80=9Crelease=E2=80=9D is more of a =
business process than a property on a
 resource. In addition I=E2=80=99d be exposing internal state that shouldn=
=E2=80=99t necessarily be exposed.</span></p></div></div></div></div></div>=
</blockquote><div><br></div><div>This is the correct way to do it. Any chan=
ge of state is a &#39;process&#39; even if all it takes is flipping a bit i=
n a database.</div><div>REST asks that you provide the *desired state* of a=
 resource (URL) and the server is responsible for transitioning from whatev=
er state it is in currently to the desired state.</div><div><br></div><div>=
For example a simple issue in an issue-tracker has a field with four values=
: reported, open, and closed. The verbs &quot;accept&quot; and &quot;re-ope=
n&quot; would both be used in natural language to describe the transitions =
to &quot;open&quot; from the other two states, but a RESTful API would only=
 allow the user to state the end value for the field, &quot;open&quot;, and=
 it would be up to the server to transition from either reported or closed =
as appropriate (or do nothing if it was already open).</div><div>=C2=A0</di=
v><blockquote class=3D"gmail_quote" style=3D"border-left:1px #ccc solid;"><=
div style=3D"background-color:#fff;"><div><div><div><div><p><span style=3D"=
font-size:11.0pt;color:#1f497d;"><u></u><u></u></span></p>
<p><u></u><span style=3D"font-size:11.0pt;color:#1f497d;"><span>2.<span sty=
le=3D"font:7.0pt &quot;Times New Roman&quot;;">=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0
</span></span></span><u></u><span style=3D"font-size:11.0pt;color:#1f497d;"=
>POST to an order-releaser resource. That=E2=80=99s more restful, but seems=
 artificial.</span></p></div></div></div></div></div></blockquote><div><br>=
</div><div>This is not RESTful, it&#39;s RPC.</div><div><br></div></div>-- =
<br><div class=3D"gmail_signature">Nicholas.</div>
</div></div>
</p>

    </div>
=20=20=20=20=20

    <!--~-|**|PrettyHtmlStart|**|-~-->
    <div style=3D"color: #fff; height: 0;">__._,_.___</div>

=20=20=20=20=20=20=20=20=20=20
=20=20
=20

=20=20=20=20
    <div style=3D"clear:both"> </div>

    <div id=3D"fromDMARC" style=3D"margin-top: 10px;">
        <hr style=3D"height:2px ; border-width:0; color:#E3E3E3; background=
-color:#E3E3E3;">
        Posted by: Nicholas Shanks &lt;[email protected]&gt;       =
 <hr style=3D"height:2px ; border-width:0; color:#E3E3E3; background-color:=
#E3E3E3;">
     </div>
    <div style=3D"clear:both"> </div>

    <table cellspacing=3D4px style=3D"margin-top: 10px; margin-bottom: 10px=
; color: #2D50FD;">
      <tbody>
        <tr>
          <td style=3D"font-size: 12px; font-family: arial; font-weight: bo=
ld; padding: 7px 5px 5px;"  >
                          <a style=3D"text-decoration: none; color: #2D50FD=
" href=3D"https://groups.yahoo.com/neo/groups/rest-discuss/conversations/me=
ssages/19729;_ylc=3DX3oDMTJxdGdrZmh0BF9TAzk3MzU5NzE0BGdycElkAzQzMTkyNTUEZ3J=
wc3BJZAMxNzA1NzAxMDE0BG1zZ0lkAzE5NzI5BHNlYwNmdHIEc2xrA3JwbHkEc3RpbWUDMTQ0Nz=
I1NjMzMQ--?act=3Dreply&messageNum=3D19729">Reply via web post</a>
                      </td>
          <td>&bull;</td>
          <td style=3D"font-size: 12px; font-family: arial; padding: 7px 5p=
x 5px;" >
            <a href=3D"mailto:[email protected]?subject=3DRe%3A%20%=
5Brest-discuss%5D%20URI%20construction%20for%20REST%20API%20and%20use%20of%=
20verbs%20as%20resource%3F" style=3D"text-decoration: none; color: #2D50FD;=
">
               Reply to sender            </a>
          </td>
          <td>&bull;</td>
          <td style=3D"font-size: 12px; font-family: arial; padding: 7px 5p=
x 5px;">
            <a href=3D"mailto:[email protected]?subject=3DRe%3A%=
20%5Brest-discuss%5D%20URI%20construction%20for%20REST%20API%20and%20use%20=
of%20verbs%20as%20resource%3F" style=3D"text-decoration: none; color: #2D50=
FD">
              Reply to group            </a>
          </td>
          <td>&bull;</td>
          <td style=3D"font-size: 12px; font-family: arial; padding: 7px 5p=
x 5px;" >
            <a href=3D"https://groups.yahoo.com/neo/groups/rest-discuss/con=
versations/newtopic;_ylc=3DX3oDMTJlODllZzl1BF9TAzk3MzU5NzE0BGdycElkAzQzMTky=
NTUEZ3Jwc3BJZAMxNzA1NzAxMDE0BHNlYwNmdHIEc2xrA250cGMEc3RpbWUDMTQ0NzI1NjMzMQ-=
-" style=3D"text-decoration: none; color: #2D50FD">Start a New Topic</a>
          </td>
          <td>&bull;</td>
          <td style=3D"font-size: 12px; font-family: arial; padding: 7px 5p=
x 5px;color: #2D50FD;" >
                            <a href=3D"https://groups.yahoo.com/neo/groups/=
rest-discuss/conversations/topics/19716;_ylc=3DX3oDMTM2bjIxOWVkBF9TAzk3MzU5=
NzE0BGdycElkAzQzMTkyNTUEZ3Jwc3BJZAMxNzA1NzAxMDE0BG1zZ0lkAzE5NzI5BHNlYwNmdHI=
Ec2xrA3Z0cGMEc3RpbWUDMTQ0NzI1NjMzMQR0cGNJZAMxOTcxNg--" style=3D"text-decora=
tion: none; color: #2D50FD;">Messages in this topic</a>
                (8)
                      </td>
        </tr>
      </tbody>
    </table>

=20=20=20=20=20=20=20=20

<!------- Start Nav Bar ------>




=20

<!-- |**|begin egp html banner|**| -->
<div id=3D"ygrp-vital" style=3D"background-color: #f2f2f2; font-family: Ver=
dana; font-size: 10px; margin-bottom: 10px; padding: 10px;">

    <span id=3D"vithd" style=3D"font-weight: bold; color: #333; text-transf=
orm: uppercase; "><a href=3D"https://groups.yahoo.com/neo/groups/rest-discu=
ss/info;_ylc=3DX3oDMTJlbnJjMzRtBF9TAzk3MzU5NzE0BGdycElkAzQzMTkyNTUEZ3Jwc3BJ=
ZAMxNzA1NzAxMDE0BHNlYwN2dGwEc2xrA3ZnaHAEc3RpbWUDMTQ0NzI1NjMzMQ--" style=3D"=
text-decoration: none;">Visit Your Group</a></span>

     <ul style=3D"list-style-type: none; margin: 0; padding: 0; display: in=
line;">
            <li style=3D"border-right: 1px solid #000; font-weight: 700; di=
splay: inline; padding: 0 5px; margin-left: 0;">
      <span class=3D"cat"><a href=3D"https://groups.yahoo.com/neo/groups/re=
st-discuss/members/all;_ylc=3DX3oDMTJmcDBqMmp1BF9TAzk3MzU5NzE0BGdycElkAzQzM=
TkyNTUEZ3Jwc3BJZAMxNzA1NzAxMDE0BHNlYwN2dGwEc2xrA3ZtYnJzBHN0aW1lAzE0NDcyNTYz=
MzE-" style=3D"text-decoration: none;">New Members</a></span>
      <span class=3D"ct" style=3D"color: #ff7900;">1</span>
    </li>
                                              </ul>
  </div>


<div id=3D"ft" style=3D"font-family: Arial; font-size: 11px; margin-top: 5p=
x; padding: 0 2px 0 0; clear: both;">
  <a href=3D"https://groups.yahoo.com/neo;_ylc=3DX3oDMTJkZXRmNjZ1BF9TAzk3ND=
c2NTkwBGdycElkAzQzMTkyNTUEZ3Jwc3BJZAMxNzA1NzAxMDE0BHNlYwNmdHIEc2xrA2dmcARzd=
GltZQMxNDQ3MjU2MzMx" style=3D"float: left;"><img src=3D"http://l.yimg.com/r=
u/static/images/yg/img/email/new_logo/logo-groups-137x15.png" height=3D"15"=
 width=3D"137" alt=3D"Yahoo! Groups" style=3D"border: 0;"/></a>
  <div style=3D"color: #747575; float: right;"> &bull; <a href=3D"https://i=
nfo.yahoo.com/privacy/us/yahoo/groups/details.html" style=3D"text-decoratio=
n: none;">Privacy</a> &bull; <a href=3D"mailto:rest-discuss-unsubscribe@yah=
oogroups.com?subject=3DUnsubscribe" style=3D"text-decoration: none;">Unsubs=
cribe</a> &bull; <a href=3D"https://info.yahoo.com/legal/us/yahoo/utos/term=
s/" style=3D"text-decoration: none;">Terms of Use</a> </div>
</div>
<br>

<!-- |**|end egp html banner|**| -->

  </div> <!-- ygrp-msg -->

=20
  <!-- Sponsor -->
  <!-- |**|begin egp html banner|**| -->
  <div id=3D"ygrp-sponsor" style=3D"width:160px; float:right; clear:none; m=
argin:0 0 25px 0; background: #fff;">

<!-- Start Recommendations -->
<div id=3D"ygrp-reco">
     </div>
<!-- End Recommendations -->



  </div>   <!-- |**|end egp html banner|**| -->

  <div style=3D"clear:both; color: #FFF; font-size:1px;">.</div>
</div>

  <img src=3D"http://geo.yahoo.com/serv?s=3D97359714/grpId=3D4319255/grpspI=
d=3D1705701014/msgId=3D19729/stime=3D1447256331" width=3D"1" height=3D"1"> =
<br>

<img src=3D"http://y.analytics.yahoo.com/fpc.pl?ywarid=3D515FB27823A7407E&a=
=3D10001310322279&js=3Dno&resp=3Dimg" width=3D"1" height=3D"1">=20

<div style=3D"color: #fff; height: 0;">__,_._,___</div>
<!--~-|**|PrettyHtmlEnd|**|-~-->

</body>

<!--~-|**|PrettyHtmlStart|**|-~-->
<head>
  <style type=3D"text/css">
  <!--
  #ygrp-mkp {
  border: 1px solid #d8d8d8;
  font-family: Arial;
  margin: 10px 0;
  padding: 0 10px;
}

#ygrp-mkp hr {
  border: 1px solid #d8d8d8;
}

#ygrp-mkp #hd {
  color: #628c2a;
  font-size: 85%;
  font-weight: 700;
  line-height: 122%;
  margin: 10px 0;
}

#ygrp-mkp #ads {
  margin-bottom: 10px;
}

#ygrp-mkp .ad {
  padding: 0 0;
}

#ygrp-mkp .ad p {
  margin: 0;
}

#ygrp-mkp .ad a {
  color: #0000ff;
  text-decoration: none;
}
  #ygrp-sponsor #ygrp-lc {
  font-family: Arial;
}

#ygrp-sponsor #ygrp-lc #hd {
  margin: 10px 0px;
  font-weight: 700;
  font-size: 78%;
  line-height: 122%;
}

#ygrp-sponsor #ygrp-lc .ad {
  margin-bottom: 10px;
  padding: 0 0;
}

  #actions {
    font-family: Verdana;
    font-size: 11px;
    padding: 10px 0;
  }

  #activity {
    background-color: #e0ecee;
    float: left;
    font-family: Verdana;
    font-size: 10px;
    padding: 10px;
  }

  #activity span {
    font-weight: 700;
  }

  #activity span:first-child {
    text-transform: uppercase;
  }

  #activity span a {
    color: #5085b6;
    text-decoration: none;
  }

  #activity span span {
    color: #ff7900;
  }

  #activity span .underline {
    text-decoration: underline;
  }

  .attach {
    clear: both;
    display: table;
    font-family: Arial;
    font-size: 12px;
    padding: 10px 0;
    width: 400px;
  }

  .attach div a {
    text-decoration: none;
  }

  .attach img {
    border: none;
    padding-right: 5px;
  }

  .attach label {
    display: block;
    margin-bottom: 5px;
  }

  .attach label a {
    text-decoration: none;
  }
=20=20
  blockquote {
    margin: 0 0 0 4px;
  }

  .bold {
    font-family: Arial;
    font-size: 13px;
    font-weight: 700;
  }

  .bold a {
    text-decoration: none;
  }

  dd.last p a {
    font-family: Verdana;
    font-weight: 700;
  }

  dd.last p span {
    margin-right: 10px;
    font-family: Verdana;
    font-weight: 700;
  }

  dd.last p span.yshortcuts {
    margin-right: 0;
  }

  div.attach-table div div a {
    text-decoration: none;
  }

  div.attach-table {
    width: 400px;
  }

  div.file-title a, div.file-title a:active, div.file-title a:hover, div.fi=
le-title a:visited {
    text-decoration: none;
  }

  div.photo-title a, div.photo-title a:active, div.photo-title a:hover, div=
.photo-title a:visited {
    text-decoration: none;
  }

  div#ygrp-mlmsg #ygrp-msg p a span.yshortcuts {
    font-family: Verdana;
    font-size: 10px;
    font-weight: normal;
  }

  .green {
    color: #628c2a;
  }

  .MsoNormal {
    margin: 0 0 0 0;
  }

  o {
    font-size: 0;
  }

  #photos div {
    float: left;
    width: 72px;
  }

  #photos div div {
    border: 1px solid #666666;
    height: 62px;
    overflow: hidden;
    width: 62px;
  }

  #photos div label {
    color: #666666;
    font-size: 10px;
    overflow: hidden;
    text-align: center;
    white-space: nowrap;
    width: 64px;
  }

  #reco-category {
    font-size: 77%;
  }

  #reco-desc {
    font-size: 77%;
  }

  .replbq {
    margin: 4px;
  }

  #ygrp-actbar div a:first-child {
   /* border-right: 0px solid #000;*/
    margin-right: 2px;
    padding-right: 5px;
  }

  #ygrp-mlmsg {
    font-size: 13px;
    font-family: Arial, helvetica,clean, sans-serif;
    *font-size: small;
    *font: x-small;
  }

  #ygrp-mlmsg table {
    font-size: inherit;
    font: 100%;
  }

  #ygrp-mlmsg select, input, textarea {
    font: 99% Arial, Helvetica, clean, sans-serif;
  }

  #ygrp-mlmsg pre, code {
    font:115% monospace;
    *font-size:100%;
  }

  #ygrp-mlmsg * {
    line-height: 1.22em;
  }

  #ygrp-mlmsg #logo {
    padding-bottom: 10px;
  }


  #ygrp-msg p a {
    font-family: Verdana;
  }

  #ygrp-msg p#attach-count span {
    color: #1E66AE;
    font-weight: 700;
  }

  #ygrp-reco #reco-head {
    color: #ff7900;
    font-weight: 700;
  }

  #ygrp-reco {
    margin-bottom: 20px;
    padding: 0px;
  }

  #ygrp-sponsor #ov li a {
    font-size: 130%;
    text-decoration: none;
  }

  #ygrp-sponsor #ov li {
    font-size: 77%;
    list-style-type: square;
    padding: 6px 0;
  }=20

  #ygrp-sponsor #ov ul {
    margin: 0;
    padding: 0 0 0 8px;
  }

  #ygrp-text {
    font-family: Georgia;
  }

  #ygrp-text p {
    margin: 0 0 1em 0;
  }

  #ygrp-text tt {
    font-size: 120%;
  }

  #ygrp-vital ul li:last-child {
    border-right: none !important;=20
  }=20
  -->
  </style>
</head>

<!--~-|**|PrettyHtmlEnd|**|-~-->
</html>
<!-- end group email -->


--089e013a06bc6cb1910524459f6f--