Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove support for non-safe REST methods #2771

Merged
merged 3 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/rest-collections/source/api.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ module api;
import vibe.web.rest;

interface ForumAPI {
@safe:
// base path /threads/
Collection!ThreadAPI threads();
}

interface ThreadAPI {
@safe:
// define the index parameters used to identify the collection items
struct CollectionIndices {
string _thread_name;
Expand All @@ -27,6 +29,7 @@ interface ThreadAPI {
}

interface PostAPI {
@safe:
// define the index parameters used to identify the collection items
struct CollectionIndices {
string _thread_name;
Expand Down
5 changes: 4 additions & 1 deletion examples/rest-collections/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ class LocalThreadAPI : ThreadAPI {

string[] get()
{
return m_data.threads.keys;
static if (__VERSION__ < 2099) {
// NOTE: .keys is not @safe on older compiler versions
return () @trusted { return m_data.threads.keys; } ();
} else return m_data.threads.keys;
}
}

Expand Down
1 change: 1 addition & 0 deletions examples/rest-js/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import vibe.http.common : HTTPMethod;

// Defines a simple RESTful API
interface ITest {
@safe:
// GET /compute_sum?a=...&b=...
@method(HTTPMethod.GET)
float computeSum(float a, float b);
Expand Down
3 changes: 3 additions & 0 deletions tests/restclient/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import vibe.vibe;

interface ITestAPI
{
@safe:
@property ISub sub();

@method(HTTPMethod.POST) @path("other/path")
Expand All @@ -22,6 +23,7 @@ interface ITestAPI
}

interface ISub {
@safe:
int get(int id);
}

Expand Down Expand Up @@ -49,6 +51,7 @@ class SubAPI : ISub {

interface ITestAPICors
{
@safe:
string getFoo();
string setFoo();
string addFoo();
Expand Down
4 changes: 4 additions & 0 deletions tests/restcollections/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ module app;
import vibe.vibe;

interface API {
@safe:
Collection!ItemAPI items();
}

interface ItemAPI {
@safe:
struct CollectionIndices {
string _item;
}
Expand All @@ -17,6 +19,7 @@ interface ItemAPI {
}

interface SubItemAPI {
@safe:
struct CollectionIndices {
string _item;
int _index;
Expand All @@ -29,6 +32,7 @@ interface SubItemAPI {
}

interface ItemManagerAPI {
@safe:
@property string databaseURL();
}

Expand Down
1 change: 1 addition & 0 deletions tests/vibe.web.rest.1125/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ shared static this()
}

interface ILlama {
@safe:
@bodyParam("llama", "llama")
string updateLlama(string llama = null);
}
Expand Down
2 changes: 2 additions & 0 deletions tests/vibe.web.rest.1140/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import vibe.d;

interface IOrientDBRoot
{
@safe:
@property IOrientDBQuery query();
}

interface IOrientDBQuery
{
@safe:
@method(HTTPMethod.GET)
@path(":db_name/sql/:query/:result_set_size")
Json sql(string _db_name, string _query, int _result_set_size);
Expand Down
1 change: 1 addition & 0 deletions tests/vibe.web.rest.1230/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import std.datetime;
import vibe.d;

interface ITestAPI {
@safe:
string postDefault(int value, bool check = true);
}

Expand Down
2 changes: 2 additions & 0 deletions tests/vibe.web.rest.1922/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ struct AuthInfo {

@requiresAuth
interface IItemAPI {
@safe:
struct CollectionIndices {
string item;
}
Expand All @@ -66,6 +67,7 @@ class ItemAPI : IItemAPI {

@requiresAuth
interface IAuthAPI {
@safe:
@noAuth int getNonAuthNumber(int num);
@anyAuth int getAuthNumber(AuthInfo info, int num);
@anyAuth Collection!IItemAPI items();
Expand Down
1 change: 1 addition & 0 deletions tests/vibe.web.rest.2506/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ struct TestStruct {int i;}

interface IService
{
@safe:
@safe TestStruct getTest(int sleepsecs);
@safe TestStruct getTest2(int sleepsecs);
}
Expand Down
1 change: 1 addition & 0 deletions tests/vibe.web.rest.auth/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ struct Auth {

@requiresAuth
interface IService {
@safe:
@noAuth int getPublic();
@anyAuth int getAny();
@anyAuth int getAnyA(Auth auth);
Expand Down
29 changes: 11 additions & 18 deletions web/vibe/web/rest.d
Original file line number Diff line number Diff line change
Expand Up @@ -1562,8 +1562,8 @@ private HTTPServerRequestDelegate jsonMethodHandler(alias Func, size_t ridx, T)(
v = fromRestString!(PT, SerPolicyType)(*pv);
} else static if (sparam.kind == ParameterKind.attributed) {
static if (!__traits(compiles, () @safe { computeAttributedParameterCtx!(CFunc, pname)(inst, req, res); } ()))
pragma(msg, "Non-@safe @before evaluators are deprecated - annotate evaluator function for parameter "~pname~" of "~T.stringof~"."~Method~" as @safe.");
v = () @trusted { return computeAttributedParameterCtx!(CFunc, pname)(inst, req, res); } ();
static assert(false, "`@before` evaluator for REST interface method `" ~ fullyQualifiedName!T ~ "." ~ Method ~ "` must be marked `@safe`.");
v = computeAttributedParameterCtx!(CFunc, pname)(inst, req, res);
} else static if (sparam.kind == ParameterKind.internal) {
if (auto pv = fieldname in req.params)
v = fromRestString!(PT, DefaultPolicy)(urlDecode(*pv));
Expand Down Expand Up @@ -1628,30 +1628,26 @@ private HTTPServerRequestDelegate jsonMethodHandler(alias Func, size_t ridx, T)(
import vibe.internal.meta.funcattr;

static if (!__traits(compiles, () @safe { __traits(getMember, inst, Method)(params); }))
pragma(msg, "Non-@safe methods are deprecated in REST interfaces - Mark " ~
T.stringof ~ "." ~ Method ~ " as @safe.");
static assert(false, "REST interface method `" ~ fullyQualifiedName!T ~ "." ~ Method ~ "` must be marked `@safe`.");

static if (is(RT == void)) {
// TODO: remove after deprecation period
() @trusted { __traits(getMember, inst, Method)(params); } ();
__traits(getMember, inst, Method)(params);
returnHeaders();
res.writeBody(cast(ubyte[])null);
} else static if (isInputStream!RT) {
returnHeaders();
auto ret = () @trusted {
return evaluateOutputModifiers!CFunc(
__traits(getMember, inst, Method)(params), req, res); } ();
auto ret = evaluateOutputModifiers!CFunc(
__traits(getMember, inst, Method)(params), req, res);
res.headers["Content-Type"] = "application/octet-stream";
ret.pipe(res.bodyWriter);
} else {
// TODO: remove after deprecation period
static if (!__traits(compiles, () @safe { evaluateOutputModifiers!Func(RT.init, req, res); } ()))
pragma(msg, "Non-@safe @after evaluators are deprecated - annotate @after evaluator function for " ~
T.stringof ~ "." ~ Method ~ " as @safe.");
static assert(false, "`@after` evaluator for REST interface method `" ~ fullyQualifiedName!T ~ "." ~ Method ~ "` must be marked `@safe`.");

auto ret = () @trusted {
return evaluateOutputModifiers!CFunc(
__traits(getMember, inst, Method)(params), req, res); } ();
auto ret = evaluateOutputModifiers!CFunc(
__traits(getMember, inst, Method)(params), req, res);
returnHeaders();

string accept_str;
Expand All @@ -1670,12 +1666,9 @@ private HTTPServerRequestDelegate jsonMethodHandler(alias Func, size_t ridx, T)(
serializer.serialize!(SerPolicyT!(RestInterface!T.I).PolicyTemplate)(serialized_output, ret);
}))
{
pragma(msg, "Non-@safe serialization of REST return types deprecated - ensure that " ~
RT.stringof~" is safely serializable.");
static assert(false, "Serialization of return type `"~RT.stringof~"` of REST interface method `" ~ fullyQualifiedName!T ~ "." ~ Method ~ "` must be `@safe`.");
}
() @trusted {
serializer.serialize!(SerPolicyT!(RestInterface!T.I).PolicyTemplate)(serialized_output, ret);
}();
serializer.serialize!(SerPolicyT!(RestInterface!T.I).PolicyTemplate)(serialized_output, ret);
res.writeBody(serialized_output.data, serializer.contentType);
}
res.statusCode = HTTPStatus.notAcceptable; // will trigger RestException on the client side
Expand Down
Loading