diff --git a/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php b/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php
index 2b246b7..42d0335 100644
--- a/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php
+++ b/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php
@@ -86,6 +86,36 @@ public function post($id, EntityInterface $entity) {
   }
 
   /**
+   * Responds to entity PUT requests.
+   *
+   * @param mixed $id
+   *   The entity ID.
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity.
+   *
+   * @return \Drupal\rest\ResourceResponse
+   *   The HTTP response object.
+   *
+   * @throws \Symfony\Component\HttpKernel\Exception\HttpException
+   */
+  public function put($id, EntityInterface $entity) {
+    if (empty($id)) {
+      throw new NotFoundHttpException();
+    }
+    $info = $entity->entityInfo();
+    // Make sure that the entity ID is the one provided in the URL.
+    $entity->{$info['entity_keys']['id']} = $id;
+    try {
+      $entity->save();
+      // Update responses have an empty body.
+      return new ResourceResponse(NULL, 200);
+    }
+    catch (EntityStorageException $e) {
+      throw new HttpException(500, 'Internal Server Error', $e);
+    }
+  }
+
+  /**
    * Responds to entity DELETE requests.
    *
    * @param mixed $id
diff --git a/core/modules/rest/lib/Drupal/rest/Tests/UpdateTest.php b/core/modules/rest/lib/Drupal/rest/Tests/UpdateTest.php
new file mode 100644
index 0000000..accf33d
--- /dev/null
+++ b/core/modules/rest/lib/Drupal/rest/Tests/UpdateTest.php
@@ -0,0 +1,88 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\rest\test\UpdateTest.
+ */
+
+namespace Drupal\rest\Tests;
+
+use Drupal\rest\Tests\RESTTestBase;
+
+/**
+ * Tests resource updates on test entities.
+ */
+class UpdateTest extends RESTTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('rest', 'entity_test');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Update resource',
+      'description' => 'Tests the update of resources.',
+      'group' => 'REST',
+    );
+  }
+
+  /**
+   * Tests several valid and invalid update requests on test entities.
+   */
+  public function testUpdate() {
+    $serializer = drupal_container()->get('serializer');
+    // @todo once EntityNG is implemented for other entity types test all other
+    // entity types here as well.
+    $entity_type = 'entity_test';
+
+    $this->enableService('entity:' . $entity_type);
+    // Create a user account that has the required permissions to create
+    // resources via the web API.
+    $account = $this->drupalCreateUser(array('restful put entity:' . $entity_type));
+    $this->drupalLogin($account);
+
+    // Create an entity and save it to the database.
+    $entity_values = $this->entityValues($entity_type);
+    $entity = entity_create($entity_type, $entity_values);
+    $entity->save();
+
+    // Create a second set of entity values that will overwrite the original.
+    $update_values = $this->entityValues($entity_type);
+    // @todo Remove the user reference field for now until deserialization for
+    // entity references is implemented.
+    unset($update_values['user_id']);
+    // Overwrite the properties with the updated values.
+    foreach ($update_values as $property => $value) {
+      $entity->set($property, $value);
+    }
+
+    $serialized = $serializer->serialize($entity, 'drupal_jsonld');
+    // Update the entity over the web API.
+    $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'PUT', $serialized, 'application/vnd.drupal.ld+json');
+    $this->assertResponse('200', 'HTTP response code is correct.');
+
+    // Re-load updated entity from the database.
+    $entity = entity_load($entity_type, $entity->id(), TRUE);
+    foreach ($update_values as $property => $value) {
+      $actual_value = $entity->get($property);
+      $this->assertEqual($value, $actual_value->value, 'Updated property ' . $property . ' expected: ' . $value . ', actual: ' . $actual_value->value);
+    }
+
+    // Try to update an entity without proper permissions.
+    $this->drupalLogout();
+    $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'PUT', $serialized, 'application/vnd.drupal.ld+json');
+    $this->assertResponse(403);
+
+    // Try to update a resource which is not web API enabled.
+    $this->enableService(FALSE);
+    // Reset cURL here because it is confused from our previously used cURL
+    // options.
+    unset($this->curlHandle);
+    $this->drupalLogin($account);
+    $this->httpRequest('entity/' . $entity_type . '/' . $entity->id(), 'PUT', $serialized, 'application/vnd.drupal.ld+json');
+    $this->assertResponse(404);
+  }
+}
