Feature #8321 ยป 0001-WIP-WResource-sequences-and-setInvalidAfterChanged.patch
src/Wt/WApplication.C | ||
---|---|---|
sizes(aSizes), disabled(aDisabled)
|
||
{ }
|
||
WApplication::ExposedResourceInfo::ExposedResourceInfo(WResource* resource,
|
||
unsigned long sequence)
|
||
: resource(resource), sequence(sequence)
|
||
{ }
|
||
bool WApplication::ScriptLibrary::operator< (const ScriptLibrary& other) const
|
||
{
|
||
return uri < other.uri;
|
||
... | ... | |
std::string WApplication::addExposedResource(WResource *resource)
|
||
{
|
||
exposedResources_[resourceMapKey(resource)] = resource;
|
||
ExposedResourceInfo exposedResourceInfo(resource);
|
||
std::string key = resourceMapKey(resource);
|
||
ResourceMap::const_iterator i = exposedResources_.find(key);
|
||
if (i != exposedResources_.end())
|
||
exposedResourceInfo = i->second;
|
||
exposedResourceInfo.sequence++;
|
||
exposedResources_[key] = exposedResourceInfo;
|
||
std::string fn = resource->suggestedFileName().toUTF8();
|
||
if (!fn.empty() && fn[0] != '/')
|
||
fn = '/' + fn;
|
||
static unsigned long seq = 0;
|
||
if (resource->internalPath().empty())
|
||
return session_->mostRelativeUrl(fn)
|
||
+ "&request=resource&resource=" + Utils::urlEncode(resource->id())
|
||
+ "&rand=" + std::to_string(seq++);
|
||
+ "&rand=" + std::to_string(exposedResourceInfo.sequence);
|
||
else {
|
||
fn = resource->internalPath() + fn;
|
||
if (!session_->applicationName().empty() && fn[0] != '/')
|
||
... | ... | |
std::string key = resourceMapKey(resource);
|
||
ResourceMap::iterator i = exposedResources_.find(key);
|
||
if (i != exposedResources_.end() && i->second == resource) {
|
||
if (i != exposedResources_.end() && i->second.resource == resource) {
|
||
#ifndef WT_TARGET_JAVA
|
||
exposedResources_.erase(i);
|
||
#else
|
||
... | ... | |
ResourceMap::const_iterator i = exposedResources_.find(resourceKey);
|
||
|
||
if (i != exposedResources_.end())
|
||
return i->second;
|
||
return i->second.resource;
|
||
else {
|
||
std::size_t j = resourceKey.rfind('/');
|
||
if (j != std::string::npos && j > 1)
|
||
... | ... | |
}
|
||
}
|
||
WResource *WApplication::decodeExposedResource(const std::string& resourceKey,
|
||
unsigned long rand) const
|
||
{
|
||
ResourceMap::const_iterator i = exposedResources_.find(resourceKey);
|
||
WResource *resource = nullptr;
|
||
if (i != exposedResources_.end())
|
||
resource = i->second.resource;
|
||
if (resource
|
||
&& resource->invalidAfterChanged()
|
||
&& (i->second.sequence != rand))
|
||
resource = nullptr;
|
||
return resource;
|
||
}
|
||
std::string WApplication::encodeObject(WObject *object)
|
||
{
|
||
std::string result = "w" + object->uniqueId();
|
src/Wt/WApplication.h | ||
---|---|---|
bool disabled;
|
||
};
|
||
struct ExposedResourceInfo {
|
||
ExposedResourceInfo(WResource* resource=nullptr, unsigned long sequence=0);
|
||
WResource* resource;
|
||
unsigned long sequence;
|
||
};
|
||
#ifndef WT_TARGET_JAVA
|
||
typedef std::map<std::string, EventSignalBase *> SignalMap;
|
||
typedef std::map<std::string, WResource *> ResourceMap;
|
||
typedef std::map<std::string, ExposedResourceInfo> ResourceMap;
|
||
#else
|
||
typedef std::weak_value_map<std::string, EventSignalBase *> SignalMap;
|
||
typedef std::weak_value_map<std::string, WResource *> ResourceMap;
|
||
typedef std::weak_value_map<std::string, ExposedResourceInfo> ResourceMap;
|
||
#endif
|
||
typedef std::map<std::string, WObject *> ObjectMap;
|
||
... | ... | |
std::string addExposedResource(WResource *resource);
|
||
bool removeExposedResource(WResource *resource);
|
||
WResource *decodeExposedResource(const std::string& resourceMapKey) const;
|
||
WResource *decodeExposedResource(const std::string& resourceMapKey,
|
||
unsigned long rand) const;
|
||
/*
|
||
* Methods for application state handling
|
src/Wt/WResource.C | ||
---|---|---|
WResource::WResource()
|
||
: trackUploadProgress_(false),
|
||
takesUpdateLock_(false),
|
||
invalidAfterChanged_(false),
|
||
dispositionType_(ContentDisposition::None),
|
||
app_(nullptr)
|
||
{
|
||
... | ... | |
dataChanged_.emit();
|
||
}
|
||
void WResource::setInvalidAfterChanged(bool enabled)
|
||
{
|
||
invalidAfterChanged_ = enabled;
|
||
}
|
||
const std::string& WResource::url() const
|
||
{
|
||
if (currentUrl_.empty())
|
src/Wt/WResource.h | ||
---|---|---|
*
|
||
* This does not work when the resource is deployed at an internal path using
|
||
* setInternalPath().
|
||
*
|
||
* \sa setInvalidAfterChanged()
|
||
*/
|
||
void setChanged();
|
||
/*! \brief Return "page not found" for prior resource URLs after change
|
||
*
|
||
* This option invalidates earlier versions of the resource url prior to
|
||
* the last call of setChanged().
|
||
*
|
||
* This does not work when the resource is deployed at an internal path using
|
||
* setInternalPath().
|
||
*
|
||
* \sa setChanged()
|
||
*/
|
||
void setInvalidAfterChanged(bool enabled);
|
||
/*! \brief Should "page not found" be returned for outdated resource URLs
|
||
*
|
||
* \sa setInvalidAfterChanged()
|
||
*/
|
||
bool invalidAfterChanged() const { return invalidAfterChanged_; }
|
||
/*! \brief Sets an internal path for this resource.
|
||
*
|
||
* Using this method you can deploy the resource at a fixed path. Unless
|
||
... | ... | |
bool trackUploadProgress_;
|
||
bool takesUpdateLock_;
|
||
bool invalidAfterChanged_;
|
||
std::vector<Http::ResponseContinuationPtr> continuations_;
|
||
src/web/WebSession.C | ||
---|---|---|
const std::string *resourceE = request.getParameter("resource");
|
||
const std::string *signalE = getSignal(request, "");
|
||
const std::string *randE = request.getParameter("rand");
|
||
if (signalE)
|
||
progressiveBoot_ = false;
|
||
... | ... | |
"<body> </body></html>";
|
||
handler.flushResponse();
|
||
} else {
|
||
if (!resource)
|
||
resource = app_->decodeExposedResource(*resourceE);
|
||
if (!resource) {
|
||
long rand = 0;
|
||
try {
|
||
if (randE)
|
||
rand = Utils::stol(*randE);
|
||
} catch (std::invalid_argument) {
|
||
rand = 0;
|
||
}
|
||
resource = app_->decodeExposedResource(*resourceE, rand);
|
||
}
|
||
if (resource) {
|
||
try {
|
||
... | ... | |
<< "' not exposed");
|
||
handler.response()->setContentType("text/html");
|
||
handler.response()->out() <<
|
||
"<html><body><h1>Nothing to say about that.</h1></body></html>";
|
||
"<html><body><h1>Page not found.</h1></body></html>";
|
||
handler.response()->setStatus(404);
|
||
handler.flushResponse();
|
||
}
|
||
}
|